WPF DataGrid通过DataContext设置CheckBox值滚动后复原如何解决?
问题根源
- DataGrid默认开启UI虚拟化,滚动时会复用单元格控件,你直接修改单元格的DataContext属于修改视图层临时值,单元格复用时会重新绑定原始数据源的属性,所以修改会丢失。
- 当前修改逻辑是直接操作单元格控件,没有修改DataGrid绑定的原始业务实体对象的属性,状态没有持久化到数据源。
- CheckBox列的绑定用了
Mode=OneTime,只会第一次加载时读取数据源的值,后续数据源变更不会通知UI更新,用户手动勾选也不会回写数据源。
修复步骤
1. 修改绑定模式
把DataGridCheckBox列的绑定从Mode=OneTime改成Mode=TwoWay,支持数据源和UI双向同步:
<DataGridCheckBoxColumn Width="0.35*" Binding="{Binding CHECK, Mode=TwoWay}">
注意你的业务实体类的CHECK属性需要实现INotifyPropertyChanged接口,否则属性变更不会通知UI更新,参考实现如下:
public class AccountItem : INotifyPropertyChanged { private bool _check; public bool CHECK { get => _check; set { _check = value; OnPropertyChanged(); } } // 其他属性STT、UID、PASSWORD等按照同样逻辑实现属性变更通知 public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 改写全选逻辑,直接修改数据源而非操作UI单元格
不要操作GetCell获取的单元格控件,直接遍历DataGrid绑定的数据源集合修改CHECK属性即可:
private void Checkallins_Click(object sender, RoutedEventArgs e) { // 把AccountItem替换成你实际绑定的业务实体类型即可 if (list_account_instagram.ItemsSource is not IEnumerable<AccountItem> items) return; bool isChecked = checkallins.IsChecked ?? false; foreach (var item in items) { item.CHECK = isChecked; } }
3. 可选方案(仅小数据量场景使用)
如果你的数据量非常小,也可以直接关闭DataGrid的UI虚拟化,避免单元格复用导致的状态丢失,不推荐大数据量场景使用,会大幅降低性能:
<DataGrid x:Name="list_account_instagram" Background="#DDDDDD" CanUserResizeColumns="False" CanUserSortColumns="False" CanUserAddRows="False" VirtualizingStackPanel.IsVirtualizing="False">
内容的提问来源于stack exchange,提问作者XYZ Mis
相关产品推荐
相关产品推荐

