在有界数据发生更改后重新排序WPF DataGrid

我正在寻找一种方法来在基础数据发生变化重新排序我的DataGrid

(设置非常标准:DataGrid的ItemSource属性绑定到ObservableCollection ;列是DataGridTextColumns ; DataGridTextColumns的数据对ObservableCollection内部的更改做出正确反应;使用鼠标单击时排序工作正常)

有任何想法吗 ?

整个下午花了我一个 小时 ,但我终于找到了一个 简单简洁高效 的解决方案

要控制所讨论的UI控件的行为(这里是一个DataGrid ),可以简单地使用CollectionViewSource 。 它可以作为ViewModel中UI控件的一种代表,而不会完全破坏MVMM模式。

在ViewModel中声明了CollectionViewSource和普通的ObservableCollection并围绕ObservableCollection包装CollectionViewSource

 // Gets or sets the CollectionViewSource public CollectionViewSource ViewSource { get; set; } // Gets or sets the ObservableCollection public ObservableCollection Collection { get; set; } // Instantiates the objets. public ViewModel () { this.Collection = new ObservableCollection(); this.ViewSource = new CollectionViewSource(); ViewSource.Source = this.Collection; } 

然后在应用程序的View部分中,您无需将CollectionControlItemsSource绑定到CollectionControl的View属性,而是直接绑定到ObservableCollection

  

从这一点开始,您可以使用ViewModel中的CollectionViewSource对象直接操作View中的UI控件。

例如排序 – 这是我的主要问题 – 看起来像这样:

 // Specify a sorting criteria for a particular column ViewSource.SortDescriptions.Add(new SortDescription ("columnName", ListSortDirection.Ascending)); // Let the UI control refresh in order for changes to take place. ViewSource.View.Refresh(); 

你看,非常非常简单和直观。 希望这有助于其他人喜欢它帮助我。

这更像是一个澄清而不是答案,但WPF 始终绑定到ICollectionView而不是源集合。 CollectionViewSource只是用于创建/检索集合视图的机制。

这是一个很好的资源,可以帮助您更好地使用WPF中的集合视图: http : //bea.stollnitz.com/blog/? p = 387

在XAML中使用CollectionViewSource实际上可以简化一些代码:

        ...   

有些人认为,在遵循MVVM模式时,视图模型应该始终公开集合视图,但在我看来,它只取决于用例。 如果视图模型永远不会直接与集合视图交互,那么在XAML中配置它会更容易。

使用LiveSorting 。 来自wpf.2000things.com的示例 。

sellmeadog的答案要么过于复杂,要么过时。 这非常简单。 你所要做的就是:

    ... 

我看不出任何明显简单的方法,所以我会尝试附加行为。 这有点像一个混蛋,但会给你你想要的东西:

 public static class DataGridAttachedProperty { public static DataGrid _storedDataGrid; public static Boolean GetResortOnCollectionChanged(DataGrid dataGrid) { return (Boolean)dataGrid.GetValue(ResortOnCollectionChangedProperty); } public static void SetResortOnCollectionChanged(DataGrid dataGrid, Boolean value) { dataGrid.SetValue(ResortOnCollectionChangedProperty, value); } ///  /// Exposes attached behavior that will trigger resort ///  public static readonly DependencyProperty ResortOnCollectionChangedProperty = DependencyProperty.RegisterAttached( "ResortOnCollectionChangedProperty", typeof (Boolean), typeof(DataGridAttachedProperty), new UIPropertyMetadata(false, OnResortOnCollectionChangedChange)); private static void OnResortOnCollectionChangedChange (DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { _storedDataGrid = dependencyObject as DataGrid; if (_storedDataGrid == null) return; if (e.NewValue is Boolean == false) return; var observableCollection = _storedDataGrid.ItemsSource as ObservableCollection; if(observableCollection == null) return; if ((Boolean)e.NewValue) observableCollection.CollectionChanged += OnCollectionChanged; else observableCollection.CollectionChanged -= OnCollectionChanged; } private static void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { if (e.OldItems == e.NewItems) return; _storedDataGrid.Items.Refresh() } } 

然后,您可以通过以下方式附加它:

    

对于其他有这个问题的人来说,这可能会让你开始…如果你有一个INotifyPropertyChanged项目的集合,你可以使用它而不是ObservableCollection – 当集合中的各个项目发生变化时它会刷新:注意:因为这会标记项目删除然后读取(即使它们实际上没有删除和添加),选择可能会不同步。 这对我的小型个人项目来说已经足够了,但还没有准备好发布给客户……

 public class ObservableCollection2 : ObservableCollection { public ObservableCollection2() { this.CollectionChanged += ObservableCollection2_CollectionChanged; } void ObservableCollection2_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.OldItems != null) foreach (object o in e.OldItems) remove(o); if (e.NewItems != null) foreach (object o in e.NewItems) add(o); } void add(object o) { INotifyPropertyChanged ipc = o as INotifyPropertyChanged; if(ipc!=null) ipc.PropertyChanged += Ipc_PropertyChanged; } void remove(object o) { INotifyPropertyChanged ipc = o as INotifyPropertyChanged; if (ipc != null) ipc.PropertyChanged -= Ipc_PropertyChanged; } void Ipc_PropertyChanged(object sender, PropertyChangedEventArgs e) { NotifyCollectionChangedEventArgs f; f = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, sender); base.OnCollectionChanged(f); f = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, sender); base.OnCollectionChanged(f); } }