You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:12:10