代码之家  ›  专栏  ›  技术社区  ›  RedGlyph sumit sonawane

CollectionViewSource仅在第一次绑定到源时排序

  •  17
  • RedGlyph sumit sonawane  · 技术社区  · 16 年前

    我正在使用绑定到CollectionViewSource的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>
    

    here ,XAML代码 here ,整个测试项目 here -除了DataGrid之外,我还为玩家添加了一个简单的列表框,以确保它不是DataGrid问题)

    (我用一个过滤器做了一个测试,但那个过滤器一直按预期工作)

    框架是.NET4。

    3 回复  |  直到 16 年前
        1
  •  15
  •   ASanch    16 年前

    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”集合),则行为将不同,并且在从父datagrid中选择不同的项之后,SortDescriptions仍将保留。

    因此,我想解决这个问题的方法是,每当父数据网格中的选定项(即“lstLevel”)发生更改时,以某种方式重新应用Players集合的排序描述。

    然而,我不是100%确定这一点,可能需要更多的测试/调查。不过,我希望我能有所贡献。=)

    编辑:

    作为建议的解决方案,您可以为lstLevel.Selection已更改在构造函数中,在设置lstLevel.ItemsSource文件财产。像这样:

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

    编辑2:

    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;
    
        2
  •  5
  •   Eren Ersönmez    14 年前

    CollectionViewSource sorting only the first time it is bound to a source

    实现您自己的数据网格:

    public class SDataGrid : DataGrid
    {
        static SDataGrid()
        {
            ItemsControl.ItemsSourceProperty.OverrideMetadata(typeof(SDataGrid), new FrameworkPropertyMetadata((PropertyChangedCallback)null, (CoerceValueCallback)null));
        }
    }
    

    清除排序描述。你可以简单地通过 覆盖元数据。在Silverlight上不可行:重写元数据API 不是公开的。虽然我不确定Silverlight是否受此影响 缺陷。其他风险和副作用可能适用。

        3
  •  5
  •   PatFromCanada    13 年前

    我只需在公开视图的属性上调用PropertyChanged,让视图刷新(并清除排序),然后添加排序描述,就可以解决这个问题。

    推荐文章