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
相关产品推荐
相关产品推荐

