CollectionViewSource排序仅在第一次被绑定到源 [英] CollectionViewSource sorting only the first time it is bound to a source

查看:352
本文介绍了CollectionViewSource排序仅在第一次被绑定到源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用绑定到一个CollectionViewSource(玩家的),本身绑定到一个列表框的当前选择的项目(的级别的),含集合的每个项目一个DataGrid要排序/在DataGrid中显示:

I'm using a DataGrid bound to a CollectionViewSource (players), itself bound to the currently selected item of a ListBox (levels), each item containing a collection to be sorted/displayed in the DataGrid:

<ListBox Name="lstLevel"
         DisplayMemberPath="Name" 
         IsSynchronizedWithCurrentItem="True" />

...

<!-- DataGrid source, as a CollectionViewSource to allow for sorting and/or filtering -->
<CollectionViewSource x:Key="Players" 
                      Source="{Binding ElementName=lstLevel, 
                                       Path=SelectedItem.Players}">
  <CollectionViewSource.SortDescriptions>
    <scm:SortDescription PropertyName="Name" />
  </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

...

  <DataGrid Name="lstPlayers" AutoGenerateColumns="False" 
            CanUserSortColumns="False"
            ItemsSource="{Binding Source={StaticResource 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>

(整个C#code 这里,XAML code的这里,整个测试项目这里 - 除了我已经在DataGrid添加了一个简单的ListBox的球员,以确保它不是一个DataGrid的问题)

(whole C# code here, XAML code here, entire test project here - in addition to the DataGrid I've added a simple ListBox for the players, to make sure it wasn't a DataGrid issue)

的问题是,玩家被分类它们显示在第一时间,但只要我请从列表框另一层面,它们不再进行排序。此外,修改名称第一次的玩家示将他们相应排序的变化,但不能再一次水平已被更改。

The problem is that the players are sorted the first time they are shown, but as soon as I select another level from the ListBox, they are not sorted anymore. Also, modifying names the first time players are shown will sort them accordingly to the changes, but not anymore once the level has been changed.

所以看起来改变CollectionViewSource源某种程度上打破了排序功能,但我不知道为什么,也不知道如何解决它。有谁知道我在做什么错了?

So it looks like changing the source of the CollectionViewSource somehow breaks the sort feature, but I have no idea why, nor how to fix it. Does anyone know what I'm doing wrong?

(我做了过滤器的测试,但一个一直工作如预期)

(I did a test with a filter, but that one kept working as expected)

该框架.NET 4。

推荐答案

大问题,一个有趣的观察。经仔细检查,似乎一个新的设置之前,DataGrid中清除一个previous的ItemsSource的排序描述。下面是它的code为OnCoerceItemsSourceProperty:

Great question and an interesting observation. Upon closer inspection, it appears that the DataGrid clears sort descriptions of a previous ItemsSource before a new one is set. Here is its code for 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代替(显示玩家集以上),则该行为会有所不同和SortDescriptions仍将从父DataGrid中选择不同的项目了。

This behavior only happens on a DataGrid. If you used a ListBox instead (to display the "Players" collection above), the behavior will be different and the SortDescriptions will still remain after selecting different items from the parent datagrid.

所以我想解决这个是以某种方式重新申请的玩家集合的排序描述每当父DataGrid中选择的项目(即lstLevel)的变化。

So I guess the solution to this is to somehow re-apply the sort descriptions of the Players collection whenever the selected item in the parent DataGrid (i.e. "lstLevel") changes.

不过,我不是100%肯定这件事,可能需要更多的测试/调查。我希望我能虽然有所贡献。 =)

However, I'm not 100% sure about this and probably needs more testing/investigation. I hope I was able to contribute something though. =)

编辑:

作为建议的解决方法,你可以把对lstLevel.SelectionChanged处理程序在你的构造,设置lstLevel.ItemsSource属性之前。事情是这样的:

As a suggested solution, you can put a handler for lstLevel.SelectionChanged in your constructor, before setting the lstLevel.ItemsSource property. Something like this:

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事件来代替。我张贴你需要下面进行必要的更新。只需复制粘贴到你的code,看看它是否工作正常。

In response to the problems you're encountering with regards to keyboard navigation, I suggest that instead of handling the "CurrentChanged" event, you handle the lstLevel.SelectionChanged event instead. I'm posting the necessary updates you need to make below. Just copy-paste to your code and see if it works fine.

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>

code-背后(构造函数):

Code-behind (constructor):

lstLevel.SelectionChanged +=
    (sender, e) =>
    {
        levels.ToList().ForEach((p) =>
        {
            CollectionViewSource.GetDefaultView(p.Players)
                .SortDescriptions
                .Add(new SortDescription("Name", ListSortDirection.Ascending));
        });
    };
lstLevel.ItemsSource = levels;

这篇关于CollectionViewSource排序仅在第一次被绑定到源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆