如何通过IValueConverter绑定DataGrid动态日期列DataGridTextColumn
WPF DataGrid动态日期列布尔值转Yes/No修复方案
问题原因
动态列未按预期显示Yes/No是两个核心问题叠加导致的:
- 动态生成列未挂载转换器:XAML中给固定列写的
Converter={StaticResource YesNoToBooleanConverter}配置仅作用于声明式写在XAML里的列,后台运行时通过new创建的动态列绑定完全没有关联转换器,因此直接显示原始布尔值 - 转换器代码存在缺陷:原有转换器中
value.tstring()为拼写错误,且直接将入参转为字符串与"true"比对的写法兼容性差,入参为布尔类型时容易出现判断错误 - 冗余逻辑:原有后台代码中定义的
truth、unTruth变量未被任何逻辑使用,属于无效代码
修复实现
1. 修正转换器代码
替换原有转换器的逻辑,直接做布尔类型判断,同时补全反向转换逻辑,避免编辑场景下的绑定错误:
Public Class YesNoToBooleanConverter Implements IValueConverter Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert ' 直接判断布尔类型入参,避免字符串转换的兼容问题 If TypeOf value Is Boolean AndAlso CBool(value) Then Return "Yes" Else Return "No" End If End Function Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack ' 实现反向转换,支持列编辑场景 Return value?.ToString() = "Yes" End Function End Class
2. 修改动态列生成逻辑
在后台创建动态列时,主动从窗口资源中取出转换器实例,赋值给对应绑定的Converter属性,同时增加列清空逻辑避免重复点击按钮重复生成列:
Class MainWindow Private Sub button1_Click(sender As Object, e As RoutedEventArgs) ' 清空已有列,避免重复点击按钮重复添加日期列 dg.Columns.Clear() Dim daysList As New DataTable() Dim startDate As New DateTime(2020, 12, 1) Dim endDate As New DateTime(2020, 12, 14) ' 从窗口资源中获取转换器实例 Dim yesNoConverter = CType(FindResource("YesNoToBooleanConverter"), YesNoToBooleanConverter) ' 循环生成日期列 Dim currentDate = startDate While currentDate <= endDate Dim columnName = currentDate.ToString("dd.MM") daysList.Columns.Add(columnName, GetType(Boolean)) ' 创建列时给绑定挂载转换器 Dim textColumn As New DataGridTextColumn() With { .Header = columnName, .Binding = New Binding("[" & columnName & "]") With { .Converter = yesNoConverter } } dg.Columns.Add(textColumn) currentDate = currentDate.AddDays(1) End While ' 生成测试行数据 Dim row = daysList.NewRow() For c As Integer = 0 To daysList.Columns.Count - 1 row(c) = (c Mod 1) = 0 Next daysList.Rows.Add(row) dg.ItemsSource = daysList.DefaultView End Sub End Class
可选优化
- 如果需要保留XAML中预先定义的固定列,去掉
dg.Columns.Clear()即可,注意加判断避免重复生成动态列 - 如果日期范围需要关联界面上的两个DatePicker选中值,把代码里写死的
startDate、endDate替换为sdate.SelectedDate、edate.SelectedDate即可,注意加空值判断 - 如果不需要编辑动态列,可以把
DataGridTextColumn配置为只读,跳过ConvertBack逻辑也不会报错
内容的提问来源于stack exchange,提问作者P Vimala
相关产品推荐
相关产品推荐

