WPF、EF:在数据网格、MVVM 中显示和保存行的顺序
本文关键字:显示 保存 顺序 网格 EF 数据 WPF 数据网 MVVM | 更新日期: 2023-09-27 18:32:40
我的用户希望能够重新排列某些数据网格和其他列表控件中的行。已经有一个具有 SortOrder 列(整数(的现有数据库。我使用实体框架 6.1。我的视图需要显示此列排序的项目,当用户单击"保存"和上下文时,对排序的任何更改也必须保存到数据库中。保存更改称为
到目前为止,我最好的尝试是将 SortOrder 列添加到我的数据网格中并按它排序(我打算以某种方式使其不可见......(,在我的视图模型中为向上/向下调用命令附加 PreviewKeyDown 事件,进而更新 SortOrder 值。但是,即使我执行 RaisePropertyChanged("MyDataGridItemSource"(,数据网格也不会更新,并且我尝试设置 mode=twoway, NotifyBySource=true, NotifyByTarget=true。完全重新设置 MyDataGridItemSource 将更新 SortOrder 列的值,但它不会根据它重新排列行,我也会丢失不需要的选择。
对于将数据库排序列映射到这样的控制器,您有什么好的建议吗?
最简单的方法是将集合包装在CollectionViewSource
中。
首先,您需要确保集合项实现INotifyPropertyChanged
,并且每当SortOrder
属性更改时都会引发PropertyChanged
事件。然后定义集合视图源,如下所示:
<CollectionViewSource x:Key="CollectionView" Source="{Binding Collection}" IsLiveSortingRequested="True">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="SortOrder" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
其中xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
,并将其放入DataGrid
祖先控件的资源字典中(例如在Window.Resources
或UserControl.Resources
中(。最后,将定义的集合视图源设置为DataGrid
的项目源:
<DataGrid ItemsSource="{Binding Source={StaticResource CollectionView}}">
...
</DataGrid>
现在,每当更改任何项SortOrder
属性时,都应相应地更新 UI。
更新
如果项目未实现INotifyPropertyChanged
则上述解决方案将不起作用。您可能需要考虑创建一个包装类,该类将公开必要的属性并实现INotifyPropertyChanged
(此设计模式通常称为"装饰器模式"(。但是,如果它不是一个选项,则可以在视图模型上定义集合视图并将其绑定到集合本身,并在对项进行任何更改时手动刷新视图。下面是它的外观示例:
public IEnumerable<Item> Collection
{
get { ... }
set
{
//store the value in the backing field
if (value != null)
{
CollectionView = CollectionViewSource.GetDefaultView(value);
CollectionView.SortDescriptions.Add(new SortDescription
{
Direction = ListSortDirection.Ascending,
PropertyName = "SortOrder",
});
}
else
CollectionView = null;
}
}
public ICollectionView CollectionView
{
get { ... }
set
{
//store the value in the backing field and raise PropertyChanged
}
}
在 XAML 中,绑定到集合视图:
<DataGrid ItemsSource="{Binding CollectionView}">
...
</DataGrid>
然后,每当对项目进行更改时,请在完成后调用CollectionView.Refresh()
,UI 将更新。