Changing CollectionViewSource Source in a MVVM world

c#, data-binding, mvvm, observablecollection, wpf

Solution

I would choose one of the two following solutions.

First, you could take your `ObservableCollection` and create an `ICollectionView` (grouping, sorting) once. Instead of replacing the `ObservableCollection` you can use `.Clear()` and add the items from the new Collection. This has the additional bonus of not breaking your grouping and sorting.

Second approach: whenever you replace your `ObservableCollection` you have to create a new `ICollectionView` for sorting and grouping.

 this._view = (ICollectionView)CollectionViewSource.GetDefaultView(this.MyCollection);

You can simply bind to your collection if you take the DefaultView

 <DataGrid Name="grid" ItemsSource="{Binding MyCollection}" />

and you can throw away your CollectionViewSource code binding stuff.

Problem

Edited: I created a new VS2010 WPF appilication with just 3 files MainWindow.xaml, MainWindow.xaml.cs, and MainWindowViewModel.cs (Listed Below). If someone feels really helpful you can recreate the problem in seconds (copy/paste). When you run the app the DataGrid will display string "OldCollection" which is wrong. If you change the ItemsSource binding to MyCollection it displays "NewCollection" which is correct. Full Description: At first I had a DataGrid with its ItemsSource bound to MyCollection. I have/need a method UpdateCollection that assigns a new ObservableCollection<> to MyCollection. With the addition of NotifyPropertyChange to MyCollection the UI updates. Next it became necessary to introduce a CollectionViewSource to enable grouping. With the UI bound to MyCollectionView, calls to UpdateCollection now have no effect. The debugger confirms that MyCollectionView always contains the initial MyCollection. How can I get my NewCollection to be reflected in the View? I have tried View.Refresh(), Binding CollectionViewSource, and countless other strategies. Note: Primarily others are concerned with the changes to Collection items not updating the view (grouping/sorting) without calling Refresh. My problem is I am assigning a brand new collection to CollectionViewSource and the view/UI never changes. ``` // 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; } } } ``` Thanks,

Original source