WPF中DevComponents AdvGridRow的ToolTip绑定与行前景色根据字段值动态设置问题
看起来你已经成功把ToolTip通过绑定的方式搞定了(终于不用再担心滚动失效的问题啦),现在卡在怎么根据FlagRead字段动态设置行的前景色——当FlagRead=0时显示红色,其他情况用默认颜色对吧?我给你两种可行的方案,你可以根据自己的习惯选:
方案一:使用值转换器(IValueConverter)
WPF里要把FlagRead的整数(0/1)转换成对应的前景色Brush,最常用的方式是写一个值转换器。首先你需要定义一个实现IValueConverter的类:
Imports System.Globalization Imports System.Windows.Data Imports System.Windows.Media Public Class ReadStatusToForegroundConverter Implements IValueConverter Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert ' 把FlagRead的整数值转换成对应的Brush If value IsNot Nothing AndAlso Integer.TryParse(value.ToString(), out Dim readStatus) Then If readStatus = 0 Then ' 未读,返回红色 Return Brushes.Red End If End If ' 已读或者值无效,返回默认值(用UnsetValue会继承父元素的前景色) Return DependencyProperty.UnsetValue End Function Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack ' 因为是OneWay绑定,不需要实现ConvertBack Throw New NotImplementedException() End Function End Class
然后,修改你创建vSetter3的代码,把这个转换器加到Binding里:
' 实例化转换器 Dim readStatusConverter As New ReadStatusToForegroundConverter() Dim vSetter3 As New Setter With vSetter3 .Property = DevComponents.WPF.Controls.AdvGridRow.ForegroundProperty ' 绑定到FlagRead字段,并使用转换器 .Value = New Binding("FlagRead") With { .Mode = BindingMode.TwoWay, .Converter = readStatusConverter } End With
这样,当行的数据里FlagRead为0时,前景色就会变成红色,其他情况会用默认的前景色。
方案二:使用DataTrigger(无需写转换器)
如果你不想写额外的转换器类,也可以在Style里添加DataTrigger,直接根据FlagRead的值设置样式。因为你是用代码创建Style的,代码如下:
Dim vStyle As New Style(GetType(DevComponents.WPF.Controls.AdvGridRow)) ' 先添加你已有的两个Setter(IsSelected和ToolTip) Dim vSetter As New Setter With vSetter .Property = DevComponents.WPF.Controls.AdvGridRow.IsSelectedProperty .Value = New Binding("Select") With {.Mode = BindingMode.TwoWay} End With vStyle.Setters.Add(vSetter) Dim vSetter2 As New Setter With vSetter2 .Property = DevComponents.WPF.Controls.AdvGridRow.ToolTipProperty .Value = New Binding("SubjectFull") With {.BindsDirectlyToSource = True} End With vStyle.Setters.Add(vSetter2) ' 添加DataTrigger:当FlagRead=0时设置前景色为红色 Dim readTrigger As New DataTrigger() readTrigger.Binding = New Binding("FlagRead") readTrigger.Value = 0 readTrigger.Setters.Add(New Setter(DevComponents.WPF.Controls.AdvGridRow.ForegroundProperty, Brushes.Red)) vStyle.Triggers.Add(readTrigger) ' 最后把Style加到DGV的Resources里 DGV.Resources.Add(GetType(DevComponents.WPF.Controls.AdvGridRow), vStyle)
这种方式更直观,直接在Style里定义条件触发的样式,不需要额外的转换器类,适合简单的条件判断场景。
补充:为什么之前遍历行设置ToolTip会失效
你之前用循环给每个AdvGridRow设置ToolTip的方式,会在滚动时失效,本质是因为DevComponents的AdvGrid和WPF原生DataGrid一样,默认开启了UI虚拟化——也就是只会创建当前可见区域的行容器,滚动时会回收复用这些行容器。你循环设置的只是当时加载的行,新滚动出来的行是复用旧的容器,它们的ToolTip还是旧数据的值,所以会乱。
而你现在用Setter绑定ToolTip到SubjectFull字段的方式,是数据驱动的:不管行容器怎么复用,它会自动绑定到当前行对应的数据项的SubjectFull,所以不管怎么滚动,ToolTip都会显示正确的值,这才是WPF推荐的方式哦。
备注:内容来源于stack exchange,提问作者gchq

