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 列的值,但它不会根据它重新排列行,我也会丢失不需要的选择。

对于将数据库排序列映射到这样的控制器,您有什么好的建议吗?

WPF、EF:在数据网格、MVVM 中显示和保存行的顺序

最简单的方法是将集合包装在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.ResourcesUserControl.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 将更新。