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

.NET Core 3.1 WPF DataGrid超40条数据时单元格边框显示异常

WPF DataGrid虚拟化滚动时单元格边框错位问题
  • 环境:.NET Core 3.1
  • 现象:开启虚拟化的DataGrid,数据条目少于40条时显示正常;超过40条并向下滚动时,单元格边框出现错位
  • 已排查4天,尝试过数据虚拟化、列表性能优化相关方案,均未解决

相关代码

DataGrid定义

<DataGrid Grid.Row="1" AlternatingRowBackground="White" HorizontalGridLinesBrush="#d4d4d4" VerticalGridLinesBrush="#d4d4d4" AutoGenerateColumns="False" CanUserAddRows="False" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserSortColumns="False" CanUserResizeColumns="False" HeadersVisibility="Column" ItemsSource="{Binding Datas}" SelectionMode="Single" SelectionUnit="FullRow" ScrollViewer.CanContentScroll="True" EnableRowVirtualization="True" VirtualizingPanel.VirtualizationMode="Recycling" VirtualizingPanel.ScrollUnit="Pixel" RowDetailsVisibilityMode="Visible" HorizontalScrollBarVisibility="Disabled">

列定义

<DataGridTextColumn Width="*" Header="Name" Binding="{Binding PropertyName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, NotifyOnValidationError=True}" EditingElementStyle="{StaticResource CellGotFocus}" ElementStyle="{StaticResource CellLostFocus}"/>
<DataGridTemplateColumn Width="*" Header="Code">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding Source, Source={vm:ReplaceModeSourceProvider}}" SelectedValue="{Binding ReplaceMode,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" DisplayMemberPath="Name" SelectedValuePath="Value"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

样式模板

<Style x:Key="CellLostFocus" TargetType="{x:Type TextBlock}">
    <Setter Property="Padding" Value="0,4,0,4"/>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="Background" Value="LightPink"/>
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="Validation.HasError" Value="True"/>
                <Condition Property="IsMouseOver" Value="True"/>
            </MultiTrigger.Conditions>
            <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)/ErrorContent}"/>
            <Setter Property="ToolTip.StaysOpen" Value="True"/>
        </MultiTrigger>
    </Style.Triggers>
</Style>
<Style x:Key="CellGotFocus" TargetType="{x:Type TextBox}">
    <Setter Property="Padding" Value="0,4,0,4"/>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="Background" Value="LightPink"/>
            <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)/ErrorContent}"/>
            <Setter Property="ToolTip.StaysOpen" Value="True"/>
        </Trigger>
    </Style.Triggers>
</Style>

可尝试的解决方向

  1. 调整虚拟化参数

    • 移除VirtualizingPanel.ScrollUnit="Pixel",改用默认的Item滚动单位,像素级滚动易引发虚拟化布局计算偏差
    • 暂时将VirtualizingPanel.VirtualizationMode从Recycling改为Standard,排查是否是行复用导致的布局状态残留
  2. 统一单元格布局尺寸

    • 给DataGrid设置固定行高,避免行内控件高度变化引发行高不一致:
      <DataGrid ... RowHeight="32"> <!-- 根据内容调整合适高度 -->
      
    • 确保所有单元格样式的内边距、对齐方式完全统一,消除布局波动诱因
  3. 强制布局刷新

    • 在DataGrid的Loaded事件中手动触发布局更新:
      private void DataGrid_Loaded(object sender, RoutedEventArgs e)
      {
          (sender as DataGrid)?.UpdateLayout();
      }
      
    • 数据绑定完成后,调用DataGrid.UpdateLayout()避免虚拟化容器尺寸计算滞后
  4. 升级.NET版本

    • .NET Core 3.1的WPF虚拟化控件存在已知布局bug,升级到.NET 5及以上版本可修复部分官方已确认的问题
  5. 自定义行模板

    • 替换默认DataGridRow模板,手动定义单元格边框和布局逻辑,避免默认模板在虚拟化场景下的布局偏差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:15:42