在MVVM世界中更改CollectionViewSource Source

aid*_*ner 8 c# data-binding wpf observablecollection mvvm

编辑:我创建了一个新的VS2010 WPF应用程序,只有3个文件MainWindow.xaml,MainWindow.xaml.cs和MainWindowViewModel.cs(下面列出).如果有人觉得非常有帮助,您可以在几秒钟内重新创建问题(复制/粘贴).当您运行应用程序时,DataGrid将显示字符串"OldCollection",这是错误的.如果将ItemsSource绑定更改为MyCollection,则显示"NewCollection",这是正确的.

完整描述: 起初我有一个DataGrid,其ItemsSource绑定到MyCollection.我需要一个方法UpdateCollection,它将一个新的ObservableCollection <>分配给MyCollection.通过向MyCollection添加NotifyPropertyChange,UI更新.

接下来,有必要引入一个CollectionViewSource来启用分组.将UI绑定到MyCollectionView后,对UpdateCollection的调用现在无效.调试器确认MyCollectionView始终包含初始MyCollection.如何让我的NewCollection反映在View中?我尝试过View.Refresh(),绑定CollectionViewSource,以及无数其他策略.

注意:其他人主要关注收集项目的更改而不更新视图(分组/排序)而不调用Refresh.我的问题是我正在为CollectionViewSource分配一个全新的集合,并且视图/ UI永远不会改变.

// MainWindow.xaml
<Window x:Class="CollectionView.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid Name="grid" ItemsSource="{Binding MyCollectionView}" />
    </Grid>
</Window>

//MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;

namespace CollectionView
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }
    }
}

//MainWindowViewModel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
using System.Windows.Data;
using System.ComponentModel;

namespace CollectionView
{
    class MainWindowViewModel : INotifyPropertyChanged
    {
        public MainWindowViewModel()
        {
            MyCollection = new ObservableCollection<MyObject>() { new MyObject() { TestString = "OldCollection" } };

            MyCollectionViewSource = new CollectionViewSource();

            // Bind CollectionViewSource.Source to MyCollection
            Binding MyBind = new Binding() { Source = MyCollection };
            BindingOperations.SetBinding(MyCollectionViewSource, CollectionViewSource.SourceProperty, MyBind);

            // The DataGrid is bound to this ICollectionView
            MyCollectionView = MyCollectionViewSource.View;

            // This assignment here to demonstrate that View/UI does not update to show "NewCollection"
            MyCollection = new ObservableCollection<MyObject>() { new MyObject() { TestString = "NewCollection" } };
        }

        // Collection Property
        // NotifyPropertyChanged added specifically to notify of MyCollection re-assignment
        ObservableCollection<MyObject> _MyCollection;
        public ObservableCollection<MyObject> MyCollection
        {
            get { return _MyCollection; }
            set
            {
                if (value != _MyCollection)
                {
                    _MyCollection = value;
                    NotifyPropertyChanged("MyCollection");
                }
            }
        }

        public CollectionViewSource MyCollectionViewSource { get; private set; }
        public ICollectionView MyCollectionView { get; private set; }

        // Method updates MyCollection itself (Called via ICommand from another ViewModel)
        public void UpdateCollection(ObservableCollection<MyObject> NewCollection)
        {
            MyCollection = NewCollection;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }

    class MyObject
    {
        public string TestString { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢,

bli*_*eis 7

我会选择以下两种解决方案之一.

首先,你可以拿走你的ObservableCollection并创建一个ICollectionView(分组,排序)一次.ObservableCollection您可以使用.Clear()并添加新Collection中的项目,而不是替换它.这还有不打破分组和排序的额外好处.

第二种方法:每当你更换你的时候,ObservableCollection你必须创建一个新 ICollectionView的排序和分组.

 this._view = (ICollectionView)CollectionViewSource.GetDefaultView(this.MyCollection);
Run Code Online (Sandbox Code Playgroud)

如果使用DefaultView,则可以简单地绑定到您的集合

 <DataGrid Name="grid" ItemsSource="{Binding MyCollection}" />
Run Code Online (Sandbox Code Playgroud)

你可以扔掉你的CollectionViewSource代码绑定的东西.