WPF DataGrid绑定DataTable时自定义CellStyle失效问题求助
适配DataTable DataView的WPF DataGrid自定义CellStyle方案
针对DataGrid绑定DataTable的DataView时,自定义CellStyle无法访问AttributeItem属性的问题,提供三种可行的适配方案:
方案1:直接绑定DataRowView的列索引器
如果你的DataTable列名与AttributeItem的属性名完全一致(如DataTable包含IsModified、ValueType列),可以直接修改绑定路径为DataRowView的索引器语法,无需额外转换:
<Style x:Key="CustomCellStyle" TargetType="DataGridCell"> <!-- 用[列名]直接访问DataRowView的列值 --> <Setter Property="IsModified" Value="{Binding [IsModified]}"/> <Setter Property="ValueType" Value="{Binding [ValueType]}"/> <!-- 其他自定义属性绑定同理 --> </Style>
适用场景:DataTable结构与AttributeItem属性完全匹配,无需额外类型转换或逻辑处理,实现成本最低。
方案2:使用值转换器转换DataRowView为AttributeItem
如果DataTable列名与AttributeItem属性名不匹配,或需要额外的类型转换逻辑,可以实现IValueConverter将DataRowView转换为AttributeItem实例:
第一步:实现转换器类
using System; using System.Globalization; using System.Windows.Data; using System.Data; public class DataRowViewToAttributeItemConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is not DataRowView rowView) return null; // 根据DataTable列映射到AttributeItem属性,可自定义转换逻辑 return new AttributeItem { IsModified = rowView.Field<bool>("IsModified"), ValueType = (ValueTypeEnum)Enum.Parse(typeof(ValueTypeEnum), rowView["ValueType"].ToString()), // 映射其他属性... }; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { // 双向绑定需要实现此方法,根据AttributeItem反向更新DataRowView if (value is not AttributeItem item) return null; return item; // 或根据需要更新对应的DataRowView列值 } }
第二步:在XAML中声明转换器资源
<Window.Resources> <local:DataRowViewToAttributeItemConverter x:Key="RowViewToAttrConverter"/> </Window.Resources>
第三步:修改CellStyle绑定
<Style x:Key="CustomCellStyle" TargetType="DataGridCell"> <Setter Property="IsModified" Value="{Binding Converter={StaticResource RowViewToAttrConverter}, Path=IsModified}"/> <Setter Property="ValueType" Value="{Binding Converter={StaticResource RowViewToAttrConverter}, Path=ValueType}"/> </Style>
适用场景:DataTable与AttributeItem结构差异较大,需要自定义转换逻辑的场景。
方案3:包装DataRowView为AttributeItem包装类
如果需要双向绑定且同步DataTable的修改,可以创建包装类将DataRowView包装为实现INotifyPropertyChanged的对象,保持与原AttributeItem属性一致的访问方式:
第一步:实现包装类
using System.ComponentModel; using System.Data; public class AttributeItemWrapper : INotifyPropertyChanged { private readonly DataRowView _rowView; public AttributeItemWrapper(DataRowView rowView) { _rowView = rowView; _rowView.RowChanged += OnRowChanged; } public bool IsModified { get => _rowView.Field<bool>("IsModified"); set { if (_rowView.Field<bool>("IsModified") != value) { _rowView["IsModified"] = value; OnPropertyChanged(nameof(IsModified)); } } } public ValueTypeEnum ValueType { get => (ValueTypeEnum)_rowView["ValueType"]; set { if ((ValueTypeEnum)_rowView["ValueType"] != value) { _rowView["ValueType"] = value; OnPropertyChanged(nameof(ValueType)); } } } // 其他属性... private void OnRowChanged(object sender, DataRowChangeEventArgs e) { // DataTable行变化时,通知属性更新 OnPropertyChanged(nameof(IsModified)); OnPropertyChanged(nameof(ValueType)); } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
第二步:转换数据源
// 将DataTable的DataView转换为包装类集合 var dataTable = GetYourDataTable(); var wrappedItems = new ObservableCollection<AttributeItemWrapper>(); foreach (DataRowView rowView in dataTable.DefaultView) { wrappedItems.Add(new AttributeItemWrapper(rowView)); } // 绑定到DataGrid的ItemsSource yourDataGrid.ItemsSource = wrappedItems;
适用场景:需要双向绑定,且DataTable数据会动态修改,需要同步UI与数据源的场景。
内容的提问来源于stack exchange,提问作者Andriy Grunov
相关产品推荐
相关产品推荐

