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

WPF DataGrid TemplateColumn滚动显示异常问题求助

问题根源与解决方案

这个问题的核心是WPF DataGrid的行虚拟化机制加上你自定义转换器里的索引获取逻辑错误导致的,咱们一步步拆解:

为什么会重复显示0-29?

你开启了EnableRowVirtualization="True"(这也是DataGrid的默认行为),这意味着DataGrid只会创建可见区域内的行容器(也就是你看到的30行),当你滚动时,它会复用这些旧容器来渲染新的数据行,而不是创建新容器。

你的RowCellConverter里用这段代码获取列索引:

int ci = dgcp.ItemContainerGenerator.IndexFromContainer(cell);

但ItemContainerGenerator.IndexFromContainer(cell)返回的是当前单元格容器在可视化树中的位置索引,不是对应数据集合的实际列索引。当容器被复用时,这个值不会随着新数据行的绑定更新,始终停留在0-29的范围内,导致你每次都取到旧行的FieldCell,自然就重复显示了。

而DataGridTextColumn不需要自定义转换器,它直接绑定到当前行的DataContext,所以能正确跟随容器复用更新内容。

怎么修复?

修改RowCellConverter的索引获取逻辑,改用DataGridCell所在列的DisplayIndex来获取对应的FieldCell——这个值是列在DataGrid中的实际顺序索引,和你的cols集合、FieldRow.cells的顺序完全对应,不会因为容器复用而出错。

修改后的Convert方法代码:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    DataGridCell cell = value as DataGridCell;
    if (cell == null) return null;

    // 获取当前单元格所在列的索引,这才是对应FieldRow.cells的正确索引
    int ci = cell.Column.DisplayIndex;

    FieldRow fr = cell.DataContext as FieldRow;
    if (fr == null) return null;

    object ret = null;
    switch ((string)parameter)
    {
        case "StateColor":
            ret = fr.cells[ci].StateColor;
            break;
        case "MyValue":
            ret = fr.cells[ci].MyValue;
            break;
        default:
            ret = fr.cells[ci];
            break;
    }
    return ret;
}

额外注意点

  • 你的代码里已经设置了CanUserReorderColumns="False",所以DisplayIndex不会因为用户拖动列而变化,完全匹配你的cols集合顺序,不用额外处理。
  • 如果以后需要允许列重排,上面的代码已经是实时获取DisplayIndex,只要cols和列的顺序对应,就可以正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:49:33