请记住 WPF 数据网格排序顺序
本文关键字:网格 排序 顺序 数据网 数据 WPF | 更新日期: 2023-09-27 18:31:24
这是这个问题的延续。
1. 设置
我有一个 wpf 窗口,其中包含一个带有动态创建项的TabControl
。此TabControl
的ItemSource
绑定到Group
的列表。这些组包含显示在TabPage
上的DataGrid
中的元素列表。
XAML:
<Window x:Name="window" x:Class="TestWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TestWpf"
Title="MainWindow" Height="350" Width="525">
<TabControl x:Name="tabControl" BorderThickness="0" ItemsSource ="{Binding Groups, ElementName=window, NotifyOnSourceUpdated=True}">
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:Group}">
<TextBlock Padding="2" Text="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate x:Name="contentTemplate" DataType="{x:Type vm:Group}">
<DataGrid x:Name="dgElements" ItemsSource="{Binding Elements, BindsDirectlyToSource=True}" DockPanel.Dock="Top" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="clmName" Header="Name" Binding="{Binding Name}" IsReadOnly="True" CanUserReorder="False" />
<DataGridTextColumn x:Name="clmDesc" Header="Description" Binding="{Binding Description}" IsReadOnly="True" CanUserReorder="False" />
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Window>
这一切都很好用。
2. 问题
该DataGrid
允许开箱即用的多列排序。但不幸的是,如果我在标签页之间切换,排序就会丢失。
我希望为每个选项卡页/数据网格维护多列排序。
可以将DataGridTextColumn
的SortDirection
绑定到属性,但这不会记住列的排序顺序。调试时我发现当我切换标签页时,SortDirection
在设置新ItemSource
之前被重置,所以我无法存储它。
问题是:如何保留每个选项卡页/数据网格的多列排序设置?
在阅读了很多文章几乎解决了我的问题后,我终于找到了解决方案。
我从DataGrid
继承了自己的类,并将每ItemSource
SortDescriptions
存储在Dictionary
中:
public class SortKeepingDataGrid : DataGrid
{
// Dictionary to keep SortDescriptions per ItemSource
private readonly Dictionary<object, List<SortDescription>> m_SortDescriptions =
new Dictionary<object, List<SortDescription>>();
protected override void OnSorting(DataGridSortingEventArgs eventArgs)
{
base.OnSorting(eventArgs);
UpdateSorting();
}
protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
base.OnItemsSourceChanged(oldValue, newValue);
ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
view.SortDescriptions.Clear();
// reset SortDescriptions for new ItemSource
if (m_SortDescriptions.ContainsKey(newValue))
foreach (SortDescription sortDescription in m_SortDescriptions[newValue])
{
view.SortDescriptions.Add(sortDescription);
// I need to tell the column its SortDirection,
// otherwise it doesn't draw the triangle adornment
DataGridColumn column = Columns.FirstOrDefault(c => c.SortMemberPath == sortDescription.PropertyName);
if (column != null)
column.SortDirection = sortDescription.Direction;
}
}
// Store SortDescriptions in dictionary
private void UpdateSorting()
{
ICollectionView view = CollectionViewSource.GetDefaultView(ItemsSource);
m_SortDescriptions[ItemsSource] = new List<SortDescription>(view.SortDescriptions);
}
}
因此,基本上,每当用户更改排序时,我都会调用UpdateSorting
并将当前SortDescription
存储在每ItemSource
字典中。
当ItemSource
发生变化时,我会查找SortDescription
并按正确的顺序重置它们。
棘手的部分是找到正确的DataGridColumn
来设置其SortDirection
。这对于绘制三角形装饰是必要的。我在这里依靠SortMemberPath
和PropertyName
的平等.最终可能需要一种更通用的方法。
在 XAML 中,我用SortKeepingDataGrid
替换了DataGrid
,现在排序按选项卡页存储。
由于我找不到任何其他解决方案,也许这也会对其他人有所帮助。