You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF DataGrid勾选Complete复选框后分组不即时更新的解决问询

问题解决与实现方案

一、解决勾选复选框后分组需切换焦点才更新的问题

1. 确保数据模型触发属性变更通知

你的测试项模型必须实现INotifyPropertyChanged接口,且Complete属性变更时要正确触发事件:

public class TestPlanItem : INotifyPropertyChanged
{
    private bool _complete;
    public bool Complete
    {
        get => _complete;
        set
        {
            if (_complete != value)
            {
                _complete = value;
                OnPropertyChanged(nameof(Complete));
            }
        }
    }

    // 其他属性(如Category、TestName等)
    public string Category { get; set; }
    public string TestName { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 开启CollectionView实时分组更新

默认的CollectionView不会在项属性变更时自动刷新分组,需启用实时分组功能:

// 获取绑定的CollectionView
var collectionView = CollectionViewSource.GetDefaultView(YourTestItemsObservableCollection);
// 开启实时分组与排序
collectionView.IsLiveGrouping = true;
collectionView.IsLiveSorting = true;
// 指定触发更新的属性
collectionView.LiveGroupingProperties.Add(nameof(TestPlanItem.Complete));
collectionView.LiveSortingProperties.Add(nameof(TestPlanItem.Complete));

3. 修正复选框列的绑定更新时机

DataGrid自动生成的复选框列默认会延迟到焦点离开时更新数据源,需手动设置UpdateSourceTrigger:

private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.PropertyName == nameof(TestPlanItem.Complete))
    {
        var checkBoxColumn = e.Column as DataGridCheckBoxColumn;
        checkBoxColumn.Binding = new Binding(nameof(TestPlanItem.Complete))
        {
            Mode = BindingMode.TwoWay,
            UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
        };
    }
}

二、解决替换ItemsPresenter为ItemsControl后分组不更新的问题

替换为ItemsControl时,必须正确绑定分组的子项集合(每个分组对象的Items属性),同时确保已开启上述实时分组配置:

<DataGrid.GroupStyle>
    <GroupStyle>
        <GroupStyle.ContainerStyle>
            <Style TargetType="{x:Type GroupItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type GroupItem}">
                            <Expander IsExpanded="True">
                                <Expander.Header>
                                    <!-- 分组头部内容 -->
                                    <TextBlock Text="{Binding Name}" FontWeight="Bold"/>
                                </Expander.Header>
                                <!-- 绑定到分组的子项集合 -->
                                <ItemsControl ItemsSource="{Binding Items}">
                                    <!-- 自定义分组内项的模板 -->
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <StackPanel Orientation="Horizontal">
                                                <CheckBox IsChecked="{Binding Complete, UpdateSourceTrigger=PropertyChanged}" Margin="0 0 10 0"/>
                                                <TextBlock Text="{Binding TestName}"/>
                                            </StackPanel>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </Expander>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </GroupStyle.ContainerStyle>
    </GroupStyle>
</DataGrid.GroupStyle>

三、添加DataTemplate控制分组项内容

1. 自定义分组头部内容

通过GroupStyle.HeaderTemplate定义分组头部的显示样式:

<DataGrid.GroupStyle>
    <GroupStyle>
        <GroupStyle.HeaderTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="类别: " FontWeight="Bold"/>
                    <TextBlock Text="{Binding Name}" Margin="5 0"/>
                    <TextBlock Text="(" Margin="5 0"/>
                    <TextBlock Text="{Binding Items.Count}" Margin="0 0 5 0"/>
                    <TextBlock Text="项,已完成: "/>
                    <TextBlock Text="{Binding Items, Converter={StaticResource CompletedCountConverter}}" Margin="0 0 5 0"/>
                </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>
                                    <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource GroupHeaderTemplate}"/>
                                </Expander.Header>
                                <ItemsPresenter/>
                            </Expander>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </GroupStyle.ContainerStyle>
    </GroupStyle>
</DataGrid.GroupStyle>

配套的已完成数量转换器:

public class CompletedCountConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is IEnumerable items)
        {
            return items.Cast<TestPlanItem>().Count(item => item.Complete);
        }
        return 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

在资源中声明转换器:

<Window.Resources>
    <local:CompletedCountConverter x:Key="CompletedCountConverter"/>
</Window.Resources>

2. 自定义分组内项的内容

关闭自动生成列,手动定义列并绑定属性,或通过DataGrid.RowTemplate实现更灵活的行样式:

<DataGrid AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridCheckBoxColumn Header="完成" Binding="{Binding Complete, UpdateSourceTrigger=PropertyChanged}"/>
        <DataGridTextColumn Header="测试项" Binding="{Binding TestName}"/>
        <DataGridTextColumn Header="类别" Binding="{Binding Category}"/>
    </DataGrid.Columns>
    <!-- 分组样式 -->
    <DataGrid.GroupStyle>
        <!-- 分组样式定义 -->
    </DataGrid.GroupStyle>
</DataGrid>

内容的提问来源于stack exchange,提问作者Pontus Holmberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 21:15:55