微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C# WPF MVVM - 当项目添加到 VM 实例中的 ObservableCollection 时,视图不会改变

如何解决C# WPF MVVM - 当项目添加到 VM 实例中的 ObservableCollection 时,视图不会改变

说明

我目前正在构建一个应用程序,如果用户在主视图上找到的组合框上触发事件,它将获取所选项目并将其添加到辅助视图上的 ObservableCollection,当用户触发事件添加项,它成功地将其添加到集合中,但不会更新 ObservableCollection 绑定的 ItemsControl 中的 UI。

问题

当 ObservableCollection 在另一个 viewmodel 中添加一个项目时,UI 不会更新。

工作列表

JobList 派生自 ObservableCollection<Job> 类型,允许在加载应用程序时使用 xml 加载稍后存储的数据,它有 6 个项目的限制。

class JobList : ObservableCollection<Job>
{
    public JobList () : base ()
    {
        if (JobListExists)
            LoadExistingJobList();
    }

    private bool JobListExists
    {
        get {

            bool result = false;

            if (File.Exists(recentsPath + @"\RecentItems.xml"))
            {
                result = true;
            }

            return result;
        }
    }

    private void LoadExistingJobList ()
    {
        using (var reader = new StreamReader(recentsPath + @"\RecentItems.xml"))
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(List<Job>),new XmlRootAttribute("Jobs"));
            List<Job> jobs = (List<Job>)deserializer.Deserialize(reader);

            foreach (Job job in jobs)
            {
                Add(job);
            }
        }
    }

    public void AddToCollection (Job job)
    {
        Insert(0,job);

        if (Count == 7)
            RemoveAt(6);
    }
}

主视图

MainView 用于 MainWindow 并存储 SearchBox(在多个地方使用)和存储 CurrentView 的 ContentControl。当事件从这里发生时,绑定到 ContentControl 的视图不会发生后续更改。

<Window.DataContext>
   <viewmodel:Mainviewmodel/>
</Window.DataContext>

    <Border Background="#272537"
            CornerRadius="15">
        <Grid>
            <Grid.ColumnDeFinitions>
                <ColumnDeFinition Width="50"/>
                <ColumnDeFinition/>
            </Grid.ColumnDeFinitions>
            
            <Grid.RowDeFinitions>
                <RowDeFinition Height="50"/>
                <RowDeFinition/>
            </Grid.RowDeFinitions>

            <Image Source="/Images/LegIcon.png" Width="30" Height="30" />

            <StackPanel Grid.Row="1">
                <RadioButton Height="40" Margin="5" Content="/Images/Home.png" Style="{StaticResource MenuButtonTheme}" IsChecked="True" Command="{Binding HomeViewCommand}"/>
                <RadioButton Height="40" Margin="5" Content="/Images/Globals.png" Style="{StaticResource MenuButtonTheme}" Command="{Binding GlobalViewCommand}"/>
            </StackPanel>
            <RadioButton Grid.Row="1" Height="40" Margin="5" Content="/Images/Settings.png" VerticalAlignment="Bottom" Style="{StaticResource MenuButtonTheme}"/>

            <StackPanel Grid.Column="1" Orientation="Horizontal">
                <ComboBox Width="190"
                     Height="40"
                     VerticalAlignment="Center"
                     HorizontalAlignment="Left"
                     Margin="5"
                     Grid.Column="1"
                     Style="{StaticResource SearchBoxTheme}"
                     ItemsSource="{Binding CurrentDropdownData}"
                        IsEditable="true"
                     displayMemberPath="Name"
                     IsSynchronizedWithCurrentItem="True">
                    <ComboBox.InputBindings>
                        <KeyBinding Gesture="Enter"
                        Command="{Binding SearchBoxCommand}"
                        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ComboBox}}}"/>
                    </ComboBox.InputBindings>
                </ComboBox>

                <Button Name="MinimizeButton" Style="{StaticResource MinimizeButton}" Margin="5" Width="40" Click="MinimizeButton_Click" />
            </StackPanel>
            <ContentControl Grid.Row="1"
                            Grid.Column="1"
                            Content="{Binding CurrentView}"/>
        </Grid>
    </Border>

主视图模型

class Mainviewmodel : ObservableObject
{
    public RelayCommand HomeViewCommand { get; set; }
    public RelayCommand GlobalViewCommand { get; set; }
    public RelayCommand SearchBoxCommand { get; set; }

    public Homeviewmodel HomeVM { get; set; }
    public Globalviewmodel GlobalVM { get; set; }

    private object _currentView;

    public object CurrentView
    {
        get { return _currentView; }
        set
        {
            _currentView = value;
            OnPropertyChanged();
        }
    }

    private ICollectionView _currentDropdownData;

    public ICollectionView CurrentDropdownData
    { 
        get { return _currentDropdownData; }
        set
        {
            _currentDropdownData = value;
            OnPropertyChanged("CurrentDropdownData");
        }
    }

    public Mainviewmodel()
    {
        CurrentDropdownData = CollectionViewSource.Getdefaultview(DataProvider.GetProjectItems());
        HomeVM = new Homeviewmodel();
        GlobalVM = new Globalviewmodel();
        CurrentView = HomeVM;

        HomeViewCommand = new RelayCommand(o =>
        {
            CurrentDropdownData = CollectionViewSource.Getdefaultview(DataProvider.GetProjectItems());
            CurrentView = HomeVM;
            SearchBoxCommand = new RelayCommand(e =>
            {
                ((Homeviewmodel)CurrentView).Collection.AddToCollection((Job)CurrentDropdownData.CurrentItem);
            });
        });

        GlobalViewCommand = new RelayCommand(o =>
        {
            CurrentDropdownData = CollectionViewSource.Getdefaultview(DataProvider.GetGlobalItems());
            CurrentView = GlobalVM;
            SearchBoxCommand = new RelayCommand(e =>
            {
            });
        });

        SearchBoxCommand = new RelayCommand(e =>
        {
            ((Homeviewmodel)CurrentView).Collection.AddToCollection((Job)CurrentDropdownData.CurrentItem);
        });
    }
}

主页视图

Home View 仅使用 ItemsControl 将“Collections”JobList 引用为 DataBinding 来显示当前选定的 Jobs

<UserControl.DataContext>
        <viewmodel:Homeviewmodel/>
    </UserControl.DataContext>
    <ItemsControl x:Name="TilePanel" ItemsSource="{Binding Collection,Mode=TwoWay}" xmlns:model="clr-namespace:JobMate_2.MVVM.Model">
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type model:Job}">
                <Border Background="#353340"
                        CornerRadius="5" 
                        Margin="5"
                        Height="50">
                    <Grid>
                        <Grid.ColumnDeFinitions>
                            <ColumnDeFinition/>
                            <ColumnDeFinition Width="25"/>
                        </Grid.ColumnDeFinitions>

                        <Grid.RowDeFinitions>
                            <RowDeFinition/>
                            <RowDeFinition/>
                        </Grid.RowDeFinitions>

                        <TextBlock Text="{Binding Name,Mode=OneWay}"
                                   Foreground="White"
                                   Margin="5"
                                   FontFamily="/Fonts/#Poppins"
                                   x:Name="JobTitle"/>

                        <Button Grid.Column="1"
                                Content="."
                                HorizontalAlignment="Stretch"
                                VerticalAlignment="Stretch"
                                Margin="2.5"
                                Visibility="Hidden"/>

                        <UniformGrid Columns="3" Grid.Row="1">
                            <Button Content="Shared" Margin="2.5" Style="{StaticResource FileLocationButton}"/>
                            <Button Content="Job Data" Margin="2.5" Style="{StaticResource FileLocationButton}"/>
                            <Button Content="Proc. Data" Margin="2.5" Style="{StaticResource FileLocationButton}"/>
                        </UniformGrid>
                    </Grid>
                </Border>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

Homeviewmodel

Homeviewmodel 非常简单地存储在视图中用于数据绑定的集合。

class Homeviewmodel : ObservableObject
{
    private JobList _collection;

    public JobList Collection
    {
        get { return _collection; }
        set
        {
            _collection = value;
            OnPropertyChanged("Collection");
        }
    }

    public Homeviewmodel ()
    {
        Collection = new JobList()
        {
            new Job () { Name = "Test" },new Job () { Name = "Test 2" },new Job () { Name = "Test 3" }
        };
    }
}

解决方法

可能只有一个原因。
您在 Window 和 UserControl 中有不同的 HomeViewModel 实例。
UserControl 不必创建自己的数据上下文。
他应该通过绑定到 CurrentView 从 Window 获取它。

,

如果您在其数据上下文中使用 MainViewModel 在 Window 中创建 UserControl 的实例,那么您需要这样的绑定:

<UserControl *****
    ***********
    DataContext="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.CurrentView}">
    <d:UserControl.DataContext>
        <viewModel:HomeViewModel/>
    </d:UserControl.DataContext>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。