Reputation: 43876
This is a continuation of this question.
I have a wpf window that contains a TabControl
with dynamically created items. The ItemSource
of this TabControl
is bound to a list of Group
s. These groups contain a list of elements that is displayed in a DataGrid
on the TabPage
.
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>
This all works fine.
The DataGrid
allows multi-column sort out of the box. But unfortunatly, if I switch between the tabpages, the sorting is lost.
I want that the multi-column sorting is maintained for each tabpage/datagrid.
It is possible to bind the SortDirection
of DataGridTextColumn
to a property, but that does not remember the sort order of the columns. And debugging I found that when I switch the tabpage, the SortDirection
is reset before the new ItemSource
is set, so I can't store this.
The question is: How can I keep the multi-column sort settings per tabpage/datagrid?
Upvotes: 3
Views: 4211
Reputation: 43876
After reading a lot of articles only almost solving my problem, I finally found a solution.
I inherited my own class from DataGrid
and stored the SortDescriptions
per ItemSource
in a 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);
}
}
So, basically, whenever the user changes the sorting, I call UpdateSorting
and store the current SortDescription
s in the per ItemSource
dictionary.
When the ItemSource
has changed, I look up the SortDescription
s and reset them in the correct order.
The tricky part is finding the correct DataGridColumn
to set its SortDirection
. This is necessary to draw the triangled adornment. I here rely on the equality of SortMemberPath
and PropertyName
. Eventually a more generic approach could be necessary.
In the XAML I replaced the DataGrid
with my SortKeepingDataGrid
and now the sorting is stored per tabpage.
Since I could not find any other solution, maybe this will help others too.
Upvotes: 12