DataGrid 分组不会随着 CollectionViewSource 的变化而更新

DataGrid grouping doesn't update on change in CollectionViewSource

我有一个 CollectionViewSource CollectionOfVideos 绑定到 ObservableCollection ListOfVideos。该 CollectionViewSource 是 DataGrid dataGrid_Video 的 ItemsSource。我已经按 lShortName of label of ListOfVideos 实施了分组。将项目添加到 DataGrid 时,分组似乎起作用了,因为它按默认 label.

对所有添加的项目进行分组

问题是,当项目的 label 发生变化时,分组不会更新。这是我的代码:

Window.Resources 在 MainWindow.xaml

<CollectionViewSource x:Key="CollectionOfVideos" Source="{Binding fosaModel.ListOfVideos, UpdateSourceTrigger=PropertyChanged}" IsLiveGroupingRequested="True" IsLiveSortingRequested="True" >
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="label" Converter="{StaticResource LTSConverter}"/>
    </CollectionViewSource.GroupDescriptions>
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="label.lShortName"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

dataGrid_Video 在 MainWindow.xaml

       <DataGrid x:Name="dataGrid_Video" 
          AutoGenerateColumns="False" 
          Margin="0,0,0,0" 
          Grid.Row="1" 
          ItemsSource="{Binding Source={StaticResource CollectionOfVideos}}" 
          GridLinesVisibility="Horizontal"
          SelectedItem="{Binding fosaModel.SelectedVideo}"
          SelectedIndex="{Binding fosaModel.SelectedVideoIndex}"
          SelectionUnit="FullRow"
          SelectionMode="Single">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding fName}" Header="Nazwa" IsReadOnly="True"></DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding AudioToSync}" Header="Dźwięk"></DataGridTextColumn>
            </DataGrid.Columns>
            <DataGrid.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" />
                            </StackPanel>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <Expander IsExpanded="True">
                                            <Expander.Header>
                                                <StackPanel Orientation="Horizontal">
                                                    <TextBlock Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}"/>
                                                </StackPanel>
                                            </Expander.Header>
                                            <ItemsPresenter />
                                        </Expander>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </DataGrid.GroupStyle>
        </DataGrid>

这是我的 fosaModel

   public class fosaModel : INotifyPropertyChanged

    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public ObservableCollection<fosaVideo> ListOfVideos { get; set; } = new ObservableCollection<fosaVideo>();
        public ObservableCollection<fosaAudio> ListOfAudios { get; set; } = new ObservableCollection<fosaAudio>();
        public ObservableCollection<fosaLabel> ListOfLabels { get; set; } = new ObservableCollection<fosaLabel>();
        public fosaVideo SelectedVideo { get; set; }
        public int SelectedVideoIndex { get; set; } = -1;
        public fosaAudio SelectedAudio { get; set; }
        public int SelectedAudioIndex { get; set; } = -1;
        public fosaLabel SelectedLabel { get; set; }
        public int SelectedLabelIndex { get; set; } = -1;
        public string WorkingDir { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        public double videoProgress { get; set; }
        public int SliderValue { get; set; }
        public bool IsDialogClosed { get; set; } = true;

    }

有几件事你应该知道:

您应该将属性的名称添加到 CollectionViewSource 的 LiveGroupingProperties 集合中:

<CollectionViewSource x:Key="CollectionOfVideos" Source="{Binding fosaModel.ListOfVideos, UpdateSourceTrigger=PropertyChanged}" 
                              IsLiveGroupingRequested="True" IsLiveSortingRequested="True"
                              xmlns:s="clr-namespace:System;assembly=mscorlib">
    <CollectionViewSource.LiveGroupingProperties>
        <s:String>label</s:String>
    </CollectionViewSource.LiveGroupingProperties>
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="label" Converter="{StaticResource LTSConverter}"/>
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

现场排序也是一样:https://wpf.2000things.com/2014/01/16/988-enabling-live-sorting-in-a-collectionviewsource/

我认为这不适用于 "label.lShortName" 等嵌套属性,所以如果您想按 T 类型的子 属性 排序ObservableCollection<T> 你需要在类型 T 中添加一个 属性 来包裹子 属性,例如:

public string lShortName
{
    get { return label.lShortName; }
    set { label.lShortName = value; NotifyPropertyChanged(); }
}