【问题标题】:DataGrid grouping doesn't update on change in CollectionViewSourceDataGrid 分组不会随着 CollectionViewSource 的变化而更新
【发布时间】:2017-05-21 18:26:18
【问题描述】:

我有一个 CollectionViewSource CollectionOfVideos 绑定到 ObservableCollection ListOfVideos。该 CollectionViewSource 是 DataGrid dataGrid_Video 的 ItemsSource。我已经按照lShortNamelabelListOfVideos 实现了分组。将项目添加到 DataGrid 时,分组似乎起作用了,因为它按默认 label 对所有添加的项目进行分组。

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

MainWindow.xaml 中的Window.Resources

<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>

MainWindow.xaml 中的 dataGrid_Video

       <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;

    }

有几件事你应该知道:

  • 我使用 Fody.PropertyChanged,所以不是 PropertyChanged 通知问题。向列表中添加新项目会更新 DataGrid。
  • 排序也不起作用。
  • ListOfVideos 中更改特定项目的 label 确实有效,我在 Debug 中进行了检查
  • 我认为 GroupingDescriptions 中 PropertyName 的点表示法有问题,所以我添加了一个转换器。带或不带转换器 - 问题仍然存在。
  • 还有一个非常相似的 CollectionViewSource,实现了排序,它可以添加新项目。
  • 我使用 MVVM Light,我希望保持 MVVM 方式。

【问题讨论】:

    标签: c# wpf mvvm datagrid collectionviewsource


    【解决方案1】:

    您应该将实时分组的属性名称添加到 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”之类的嵌套属性,因此如果您想在ObservableCollection&lt;T&gt; 中按T 类型的子属性进行排序,您需要添加一个属性为包裹子属性的T 类型,例如:

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

    【讨论】:

    • 在 ListOfVideos 类中实现 INotifyPropertyChanged 效果很好,我什至不必添加那些 LiveGroupingProperties。所以原来是PropertyChanged问题。非常感谢!
    猜你喜欢
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多