【问题标题】:WPF, EF: Show and save ordering of rows in datagrid, mvvmWPF、EF:在数据网格、mvvm 中显示和保存行的顺序
【发布时间】:2014-12-01 08:19:41
【问题描述】:

我的用户希望能够重新排列某些数据网格和其他列表控件中的行。已有一个带有 SortOrder 列(整数)的数据库。我使用实体框架 6.1。我的视图需要显示按此列排序的项目,并且当用户单击“保存”并调用 context.SaveChanges 时,对排序的任何更改也必须保存到数据库中

到目前为止,我最好的尝试是在我的数据网格中添加一个 SortOrder 列并按它排序(我打算以某种方式使其不可见......),在我的视图模型中为调用命令的 up/down 附加 PreviewKeyDown 事件,即依次更新 SortOrder 值。但是,即使我执行 RaisePropertyChanged("MyDataGridItemSource"),数据网格也不会更新,并且我尝试设置 mode=twoway、NotifyBySource=true、NotifyByTarget=true。完全重新设置 MyDataGridItemSource 将更新 SortOrder 列的值,但不会根据它重新排列行,而且我也会丢失不需要的选择。

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

【问题讨论】:

    标签: c# wpf mvvm datagrid


    【解决方案1】:

    最简单的方法是将集合包装在 CollectionViewSource 中。

    首先,您需要确保集合项实现INotifyPropertyChangedPropertyChanged 事件,只要SortOrder 属性更改就会引发。然后像这样定义集合视图源:

    <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 将会更新。

    【讨论】:

    • 我绑定到的集合是一个属性,它返回有问题的实体框架实体,因此这些项目不实现 INotifyPropertyChanged,但是,我可以在更改 SortOrder 时引发事件,这样也行吗?
    • 我更改了实体框架生成类的方式,以便它们现在实现 INotifyPropertyChanged,然后让您的第一个解决方案正常工作,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    相关资源
    最近更新 更多