C# WPF中DataGridComboBoxColumn选中值串显、滚动丢值问题
问题根因
遇到的两个异常都是代码实现错误导致的,和DataGridComboBoxColumn控件本身无关,具体问题点如下:
Time类存在两个硬伤:一是Hour、Minute属性只写了set访问器,没有公开get访问器,外部根本无法读取时间值;二是没有重写Equals和GetHashCode方法,WPF绑定机制默认按引用判断对象相等,值相同但引用不同的Time实例会被判定为不相等,直接导致下拉选中值无法正确匹配,滚动时DataGrid虚拟化复用行容器就会出现值丢失的问题。TimeConverter逻辑完全错误:DataGridComboBoxColumn的SelectedItem要求绑定返回值类型和ItemsSource内的元素类型一致(即Time类型),但转换器的Convert方法把Time实例转成了字符串返回,根本无法和下拉源里的Time项匹配;ConvertBack方法直接强转参数,没有做类型校验,极易触发运行时异常。WorkDay类没有实现INotifyPropertyChanged接口,ArrivalTime属性值变更时无法通知UI刷新,会引发绑定错乱,出现选中一个值其他单元格同步显示相同内容的问题。
修复步骤
按以下顺序修改代码即可解决所有异常:
- 修复
Time类,补上属性get访问器,重写值相等判断逻辑:
class Time { private int _hour = 0; private int _minute = 0; public int Hour { get => _hour; set => _hour = value; } public int Minute { get => _minute; set => _minute = value; } public override string ToString() { var fmt = "D2"; return _hour.ToString(fmt) + ":" + _minute.ToString(fmt); } // 值相同的Time实例判定为相等 public override bool Equals(object obj) { if (obj is Time other) { return other.Hour == Hour && other.Minute == Minute; } return false; } public override int GetHashCode() { return HashCode.Combine(Hour, Minute); } }
- 完全移除
TimeConverter类,同时删除XAML中对应的资源注册、绑定里的Converter配置,修正后的DataGridComboBoxColumn配置如下:
<DataGridComboBoxColumn Header="Arrival Time" ItemsSource="{StaticResource times}" SelectedItemBinding="{Binding ArrivalTime, UpdateSourceTrigger=PropertyChanged}" />
- 给
WorkDay类实现INotifyPropertyChanged接口,保证属性变更能正确通知UI刷新:
using System.ComponentModel; using System.Runtime.CompilerServices; class WorkDay : INotifyPropertyChanged { private Time _arrivalTime; public Time ArrivalTime { get => _arrivalTime; set { _arrivalTime = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
补充说明
- 该场景只有31行数据,就算关闭DataGrid的虚拟化也不会有性能问题,如果修改后仍有偶发显示异常,可以给DataGrid附加属性
VirtualizingStackPanel.IsVirtualizing="False"关闭行虚拟化,不过按上述步骤修复后,默认开启虚拟化也不会出现值丢失问题。 - 修复完成后下拉选择、滚动浏览、值持久化都会正常工作,不会再出现值同步错乱、滚动消失的问题。
内容的提问来源于stack exchange,提问作者user8105480
相关产品推荐
相关产品推荐

