我的用户希望能够在一些数据网格和其他列表控件中重新排列行。已存在具有SortOrder列(整数)的现有数据库。我使用实体框架6.1。我的视图需要显示此列所订购的项目,并且当用户单击" save"时,必须将对订单的任何更改保存到数据库中。和context.SaveChanges被称为
到目前为止,我最好的尝试是将一个SortOrder列添加到我的datagrid并按它排序(我打算让它以某种方式隐藏...),在我的viewmodel中为up / down调用命令附加PreviewKeyDown事件,反过来更新SortOrder值。但是,即使我执行RaisePropertyChanged(" MyDataGridItemSource"),数据网格也不会更新,我已经尝试设置mode = twoway,NotifyBySource = true,NotifyByTarget = true。完全重新设置MyDataGridItemSource将更新SortOrder列的值,但它不会根据它重新排列行,而且我也会丢失我不需要的选择。
对于将数据库排序列映射到这样的控制器,您有什么好的建议吗?
答案 0 :(得分:1)
最简单的方法是将集合包装在CollectionViewSource
。
首先,您需要确保集合项实现INotifyPropertyChanged
,并且只要PropertyChanged
属性发生更改,就会引发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.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。