更改
DataGrid
后如何保留 ItemsSource
中列的排序?
以下代码保留排序,但不会将
DataGrid
的列标题设置为“已排序”状态(因此没有“排序”图标之类的东西):
SortDescriptionCollection sortDescriptions = new SortDescriptionCollection();
foreach (SortDescription sd in OccupationsDataGrid.Items.SortDescriptions)
{
sortDescriptions.Add(sd);
}
OccupationsDataGrid.ItemsSource = q;
foreach (SortDescription sd in sortDescriptions)
{
OccupationsDataGrid.Items.SortDescriptions.Add(sd);
}
使用 Telerik 的 JustDecompile 并查看 DataGrid。
在 DataGrid 的静态构造函数中,我们有这一行:
ItemsControl.ItemsSourceProperty.OverrideMetadata(type, new FrameworkPropertyMetadata(null, new CoerceValueCallback(DataGrid.OnCoerceItemsSourceProperty)));
因此当 ItemsSource 更改时,将调用 DataGrid.OnCoerceItemsSourceProperty。它的定义是这样的:
private static object OnCoerceItemsSourceProperty(DependencyObject d, object baseValue)
{
DataGrid dataGrid = (DataGrid)d;
if (baseValue != dataGrid._cachedItemsSource && dataGrid._cachedItemsSource != null)
{
dataGrid.ClearSortDescriptionsOnItemsSourceChange();
}
return baseValue;
}
它最终调用 ClearSortDescriptionsOnItemsSourceChange。这是哪一个:
private void ClearSortDescriptionsOnItemsSourceChange()
{
base.Items.SortDescriptions.Clear();
this._sortingStarted = false;
List<int> groupingSortDescriptionIndices = this.GroupingSortDescriptionIndices;
if (groupingSortDescriptionIndices != null)
{
groupingSortDescriptionIndices.Clear();
}
foreach (DataGridColumn column in this.Columns)
{
column.SortDirection = null;
}
}
看起来该列的 SortDirection 正在被擦除,并且必须控制排序箭头的外观。所以......当我们添加排序描述时,我们应该把它放回去。更改重新添加 SortDescriptions 的循环:
foreach (SortDescription sd in sortDescriptions)
{
OccupationsDataGrid.Items.SortDescriptions.Add(sd);
foreach (var col in OccupationsDataGrid.Columns.Where(aa => aa.SortMemberPath == sd.PropertyName))
{
col.SortDirection = sd.Direction;
}
}
我在更改 ItemsSource 时一直在处理类似的问题,它破坏了新 ItemsSource 的排序描述,并且只是默认返回默认排序。
public class CustomDataGrid : DataGrid
{
static CustomDataGrid()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomDataGrid), new FrameworkPropertyMetadata(typeof(CustomDataGrid)));
// Override Coerce of ItemsSourceProperty
ItemsSourceProperty.OverrideMetadata(typeof(CustomDataGrid), new FrameworkPropertyMetadata(null, OnCoercItemsSource));
}
private static object OnCoercItemsSource(DependencyObject d, object basevalue)
{
// DataGrid messes up sorting changing the ItemsSource. Overriding this method
// to do nothing fixes that issue, and keeps column sorting intact when changing ItemsSource.
return basevalue;
}
}
以下代码修复了排序中断的问题,并且还保留了数据网格的当前列排序。