首页 > 解决方案 > 项目属性更改时更新数据网格的 GroupHeader

问题描述

我在更新某个绑定时遇到了一些困难。

我有一个加载一些设备的类 DeviceList,它继承自 ObservableCollection 并在我的 XAML 中列为资源:

<local:DeviceList x:Key="Devices" />

然后,我有一个使用此设备列表作为源的 CollectionViewSource,并按设备中的属性对其进行分组:

<CollectionViewSource x:Key="cvsDevices" Source="{StaticResource Devices}" Filter="CollectionViewSource_Filter">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="GroupId" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

绑定到此 CVS 的 Datagrid,它具有组标题样式:

<DataGrid x:Name="dataGrid" ItemsSource="{Binding Source={StaticResource cvsDevices}}">
    <DataGrid.GroupStyle>
        <GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
            <GroupStyle.Panel>
                <ItemsPanelTemplate>
                    <DataGridRowsPresenter />
                </ItemsPanelTemplate>
            </GroupStyle.Panel>
        </GroupStyle>
    </DataGrid.GroupStyle>
    <DataGrid.Columns>
        bla bla
    </DataGrid.Columns>
</DataGrid>

最后是资源中的 Group Header 样式:

<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type GroupItem}">
                <Expander IsExpanded="True" Background="White" Foreground="Black">
                    <Expander.Header>
                        <StackPanel Orientation="Horizontal" Height="30">
                            <Border Margin="5" Width="20" Height="20" Background="{Binding Path=Items, Converter={StaticResource DeviceGroupToColorConverter}}" CornerRadius="10" />
                            <TextBlock VerticalAlignment="Center" Padding="3" Text="{Binding Name, Converter={StaticResource DeviceGroupToGroupTitleConverter}}" />
                            <TextBlock VerticalAlignment="Center" Padding="3" Text="{Binding ItemCount, Converter={StaticResource ItemCountToStringConverter}}"/>
                        </StackPanel>
                    </Expander.Header>
                    <ItemsPresenter />
                </Expander>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

如您所见,那里有一个绑定到“项目”的边框。这是“CollectionViewGroup”的属性:https ://docs.microsoft.com/en-us/dotnet/api/system.windows.data.collectionviewgroup?view=netcore-3.1

基本上我的每个设备都有一个属性“连接”,当这个属性发生变化时,我想在相应的组标题中设置这个边框的颜色。

绑定第一次工作正常,但之后当连接更改时不再调用 DeviceGroupToColorConverter。设备实现了 INotifyPropertyChanged,但我不知道如何将该事件传播到 CollectionViewGroup 的 Items 属性。事实上,我不知道 CollectionViewGroup 实例在哪里。我只能访问 CollectionViewSource。

我想避免刷新整个 DataGrid。我已经读过它重置了我的扩展器,而且,当只有某个组的标题应该更改时,为什么要刷新整个数据网格?

标签: c#.netwpf.net-coredata-binding

解决方案


我已经通过将绑定更改为 MultiBinding 并将具有 Source 集的绑定添加到 DeviceList 来解决它:

<Border Margin="5" Width="20" Height="20" CornerRadius="10">
    <Border.Background>
        <MultiBinding Converter="{StaticResource DeviceGroupToColorConverter}">
            <Binding Source="{StaticResource Devices}" Path="Devices" />
            <Binding Path="Name" />
        </MultiBinding>
    </Border.Background>
</Border>

DeviceList 类的“Devices”属性是一个简单的 getter,它返回“this”:

public ObservableCollection<Device> Devices 
{ 
    get 
    {
        return this;
    } 
}

我让 DeviceList 监听设备上的任何属性更改,并在 DeviceList 的“Devices”属性上调用 PropertyChanged 以将此事件传递给 MultiBinding。

然后,我使用 MultiBinding 中的 Name 绑定,根据设备所在的组过滤设备。现在我不需要刷新整个网格,我的性能很好。


推荐阅读