DataGrid grouping doesn't update on change in CollectionViewSource

天大地大妈咪最大 提交于 2019-12-25 05:08:12

问题


I have a CollectionViewSource CollectionOfVideos bound to ObservableCollection ListOfVideos. That CollectionViewSource is the ItemsSource for the DataGrid dataGrid_Video. I've implemented a grouping by lShortName of label of ListOfVideos. When items are added to DataGrid, grouping seems to work, because it groups all added items by their default label.

Problem is, grouping doesn't update when label of item is changed. Here's my code:

Window.Resources in 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 in 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>

Here's my 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;

    }

There are few things you should know:

  • I use Fody.PropertyChanged, so it's not PropertyChanged notification problem. Adding new items to the list updates the DataGrid.
  • Sorting doesn't work either.
  • Changing label of particular item in ListOfVideos does work, I checked in Debug
  • I thought it was a problem with dot notation of PropertyName in GroupingDescriptions, so I've added a converter. With or without converter - problem still exists.
  • There is also very similar CollectionViewSource, with sorting implemented, and it works on adding new item.
  • I use MVVM Light and I'd like to keep it MVVM way.

回答1:


You should add the names of the properties to live group by to the LiveGroupingProperties collection of the CollectionViewSource:

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

It's the same for the live sorting: https://wpf.2000things.com/2014/01/16/988-enabling-live-sorting-in-a-collectionviewsource/

I don't think this will work with nested properties such as "label.lShortName" though so if you want to live sort by a sub-property of the type T in your ObservableCollection<T> you need to add a property to the type T that wraps the sub-property, e.g.:

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


来源:https://stackoverflow.com/questions/41515053/datagrid-grouping-doesnt-update-on-change-in-collectionviewsource

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!