WPF DataGrid Toolkit滚动后列绘制异常及日期单元格着色问题求助
解决WPF DataGrid Toolkit滚动后列绘制异常问题
嘿,这个滚动后样式乱掉的问题我太熟悉了!大概率是DataGrid默认的UI虚拟化在搞事情——滚动时它会复用行和单元格容器,如果你之前是直接在代码里修改样式(比如后台代码、或者绑定逻辑里直接赋值),旧的样式状态没被正确重置,就会出现滚动后样式串位的情况。下面给你几个靠谱的解决方案,按优先级来:
1. 用样式触发器+数据绑定实现动态样式(推荐)
完全让样式由数据驱动,依赖WPF的触发器机制,这样虚拟化复用容器时,触发器会自动根据当前行的数据重新计算样式,不会残留旧状态。
第一步:写日期比较转换器
先创建一个IValueConverter实现,用来判断MyDate1是否大于MyDate2:
public class DateGreaterThanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // 先做空值判断,避免空引用异常 if (value is not DateTime date1 || parameter is not DateTime date2) return false; return date1 > date2; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException("不需要反向转换"); } }
第二步:定义单元格样式
在你的Window/UserControl的Resources里注册转换器和单元格样式:
<Window.Resources> <local:DateGreaterThanConverter x:Key="DateGreaterThanConverter"/> <Style x:Key="DateColumnCellStyle" TargetType="tk:DataGridCell"> <!-- 默认背景透明 --> <Setter Property="Background" Value="Transparent"/> <Style.Triggers> <!-- 多条件触发器:当两个日期都不为空,且MyDate1>MyDate2时,设置橙红色背景 --> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding MyDate1}" Value="{x:Null}" Operator="NotEqual"/> <Condition Binding="{Binding MyDate2}" Value="{x:Null}" Operator="NotEqual"/> <Condition Binding="{Binding MyDate1}" Converter="{StaticResource DateGreaterThanConverter}" ConverterParameter="{Binding MyDate2}" Value="True"/> </MultiDataTrigger.Conditions> <Setter Property="Background" Value="#FFCC5533"/> <!-- 橙红色 --> </MultiDataTrigger> </Style.Triggers> </Style> </Window.Resources>
第三步:给Date1和Date2列应用样式
在DataGrid的列定义里引用这个样式:
<tk:DataGridTextColumn Header="Date1" Binding="{Binding MyDate1, StringFormat={}{0:yyyy-MM-dd}}" CellStyle="{StaticResource DateColumnCellStyle}"/> <tk:DataGridTextColumn Header="Date2" Binding="{Binding MyDate2, StringFormat={}{0:yyyy-MM-dd}}" CellStyle="{StaticResource DateColumnCellStyle}"/>
整行颜色也用同样逻辑处理
如果你的整行颜色是通过VM属性控制的,也用DataTrigger实现,不要直接在代码里修改行的Background:
<Style TargetType="tk:DataGridRow"> <Style.Triggers> <DataTrigger Binding="{Binding RowHighlightCondition}" Value="True"> <Setter Property="Background" Value="LightGreen"/> </DataTrigger> </Style.Triggers> </Style>
2. 临时应急:关闭UI虚拟化(不推荐)
如果赶时间可以先试试这个,但大数据量下会严重影响性能,因为DataGrid会渲染所有行:
<tk:DataGrid VirtualizingStackPanel.IsVirtualizing="False" VirtualizingStackPanel.VirtualizationMode="Standard"/>
关键原理
WPF DataGrid的虚拟化是为了性能优化,滚动时只会渲染可见区域的行,并且复用离开可视区域的行容器。如果你的样式不是通过数据绑定的触发器实现,而是直接修改容器的属性,复用的时候旧属性值不会被自动重置,就会出现样式串位的问题。用触发器+数据绑定的方式,每次容器复用都会重新绑定当前行的数据,触发器会重新计算样式,自然就不会有异常了。
内容的提问来源于stack exchange,提问作者Willy
相关产品推荐
相关产品推荐

