Отличный вопрос и интересное наблюдение. При ближайшем рассмотрении выясняется, что DataGrid очищает описания сортировки предыдущего элемента ItemsSource до того, как будет установлен новый. Вот его код для OnCoerceItemsSourceProperty:
private static object OnCoerceItemsSourceProperty(DependencyObject d, object baseValue)
{
DataGrid grid = (DataGrid) d;
if ((baseValue != grid._cachedItemsSource) && (grid._cachedItemsSource != null))
{
grid.ClearSortDescriptionsOnItemsSourceChange();
}
return baseValue;
}
Это происходит только в DataGrid. Если вместо этого вы использовали ListBox (для отображения коллекции «Players» выше), поведение будет другим, и описания SortDescription останутся после выбора других элементов из родительской таблицы данных.
Так что я думаю, что решение этой проблемы состоит в том, чтобы каким-то образом повторно применять описания сортировки коллекции Players при каждом изменении выбранного элемента в родительской DataGrid (то есть "lstLevel").
Однако я не уверен на 100% в этом и, вероятно, нуждаюсь в дополнительном тестировании / расследовании. Я надеюсь, что смог что-то внести, хотя. =)
EDIT:
В качестве предлагаемого решения вы можете поместить обработчик для lstLevel.SelectionChanged в свой конструктор перед установкой свойства lstLevel.ItemsSource. Примерно так:
lstLevel.SelectionChanged +=
(sender, e) =>
{
levels.ToList().ForEach((p) =>
{
CollectionViewSource.GetDefaultView(p.Players)
.SortDescriptions
.Add(new SortDescription("Name", ListSortDirection.Ascending));
});
};
lstLevel.ItemsSource = levels;
EDIT2:
В ответ на проблемы, с которыми вы сталкиваетесь при навигации по клавиатуре, я предлагаю вместо обработки события CurrentChanged вместо этого обработать событие lstLevel.SelectionChanged. Я публикую необходимые обновления, которые нужно сделать ниже. Просто скопируйте и вставьте ваш код и посмотрите, работает ли он нормально.
XAML:
<!-- Players data, with sort on the Name column -->
<StackPanel Grid.Column="1">
<Label>DataGrid:</Label>
<DataGrid Name="lstPlayers" AutoGenerateColumns="False"
CanUserSortColumns="False"
ItemsSource="{Binding ElementName=lstLevel, Path=SelectedItem.Players}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name"
Binding="{Binding Path=Name, Mode=TwoWay}"
Width="*" />
<DataGridTextColumn Header="Age"
Binding="{Binding Path=Age, Mode=TwoWay}"
Width="80">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
<StackPanel Grid.Column="2">
<Label>ListBox:</Label>
<ListBox ItemsSource="{Binding ElementName=lstLevel, Path=SelectedItem.Players}" DisplayMemberPath="Name" />
</StackPanel>
Кодовый код (конструктор):
lstLevel.SelectionChanged +=
(sender, e) =>
{
levels.ToList().ForEach((p) =>
{
CollectionViewSource.GetDefaultView(p.Players)
.SortDescriptions
.Add(new SortDescription("Name", ListSortDirection.Ascending));
});
};
lstLevel.ItemsSource = levels;