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

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刷新,会引发绑定错乱,出现选中一个值其他单元格同步显示相同内容的问题。
修复步骤

按以下顺序修改代码即可解决所有异常:

  1. 修复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);
    }
}
  1. 完全移除TimeConverter类,同时删除XAML中对应的资源注册、绑定里的Converter配置,修正后的DataGridComboBoxColumn配置如下:
<DataGridComboBoxColumn Header="Arrival Time"
                        ItemsSource="{StaticResource times}"
                        SelectedItemBinding="{Binding ArrivalTime, UpdateSourceTrigger=PropertyChanged}" />
  1. 给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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:06:29