这是this question的延续。
我有一个wpf窗口,其中包含一个动态创建的项目TabControl
。此ItemSource
的{{1}}绑定到TabControl
列表。这些组包含Group
上DataGrid
显示的元素列表。
XAML:
TabPage
一切正常。
<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>
允许多列开箱即用。但不幸的是,如果我在标签之间切换,排序就会丢失
我希望为每个tabpage / datagrid 维护多列排序。
可以将DataGrid
的{{1}}绑定到属性,但不记得列的排序顺序。调试我发现当我切换标签页时,SortDirection
在设置新的DataGridTextColumn
之前重置了,所以我无法存储它。
问题是:如何保留每个tabpage / datagrid的多列排序设置?
答案 0 :(得分:8)
在阅读了很多文章后,我几乎找到了解决问题的方法
我从$broadcast
继承了自己的班级,并将$on
按DataGrid
存储在SortDescriptions
中:
ItemSource
因此,基本上,每当用户更改排序时,我都会调用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
的平等。最终可能需要更通用的方法。
在XAML中,我将SortMemberPath
替换为我的PropertyName
,现在每个标签页都存储了排序。
由于我找不到任何其他解决方案,也许这对其他人也有帮助。