.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>
可尝试的解决方向
调整虚拟化参数
- 移除
VirtualizingPanel.ScrollUnit="Pixel",改用默认的Item滚动单位,像素级滚动易引发虚拟化布局计算偏差 - 暂时将
VirtualizingPanel.VirtualizationMode从Recycling改为Standard,排查是否是行复用导致的布局状态残留
- 移除
统一单元格布局尺寸
- 给DataGrid设置固定行高,避免行内控件高度变化引发行高不一致:
<DataGrid ... RowHeight="32"> <!-- 根据内容调整合适高度 --> - 确保所有单元格样式的内边距、对齐方式完全统一,消除布局波动诱因
- 给DataGrid设置固定行高,避免行内控件高度变化引发行高不一致:
强制布局刷新
- 在DataGrid的
Loaded事件中手动触发布局更新:private void DataGrid_Loaded(object sender, RoutedEventArgs e) { (sender as DataGrid)?.UpdateLayout(); } - 数据绑定完成后,调用
DataGrid.UpdateLayout()避免虚拟化容器尺寸计算滞后
- 在DataGrid的
升级.NET版本
- .NET Core 3.1的WPF虚拟化控件存在已知布局bug,升级到.NET 5及以上版本可修复部分官方已确认的问题
自定义行模板
- 替换默认DataGridRow模板,手动定义单元格边框和布局逻辑,避免默认模板在虚拟化场景下的布局偏差
内容的提问来源于stack exchange,提问作者Hieu Pham
相关产品推荐
相关产品推荐

