Avalonia中,使用DataTable类型作为DataGrid的ItemSource 数据源

1.描述

假设:后端查询返回的是一个DataTable类型的结果

问题:发现

复制代码
ExistingProductionInfoDgvItemSource = dt;

或者

复制代码
ExistingProductionInfoDgvItemSource = dt.DefaultView均无法显示数据。。。

绑定为DataView类型会显示一段奇怪的东西出来,这里忘记截图了

2.代码

2.1View

XML 复制代码
                        <DataGrid
                            x:Name="ExistingProductionInfoDgv"
                            SelectedItem="{Binding SelectedConfProduct, Mode=TwoWay}"
                            ItemsSource="{Binding ExistingProductionInfoDgvItemSource.DefaultView}"
                            PointerReleased="ExistingProductionInfoDgv_OnPointerReleased"
                            AutoGenerateColumns="False"
                            GridLinesVisibility="All"/>

2.2ViewModel 的绑定

cs 复制代码
    private DataTable _existingProductionInfoDgvItemSource = new DataTable();

    public DataTable ExistingProductionInfoDgvItemSource
    {
        get => _existingProductionInfoDgvItemSource;
        set
        {
            _existingProductionInfoDgvItemSource = value;
            NotifyChanged();
            // 数据-赋值 传递dt-value给View的后置代码
            // DataTableUpdated?.Invoke(this,value);
            DataTableUpdated?.Invoke(this, _existingProductionInfoDgvItemSource);
        }
    }

    // 数据更新事件(联动View生成列)--代码后置
    public event EventHandler<DataTable> DataTableUpdated;


//查询赋值
    #region 初始化查询-刷新

    //获取数据
    private void GetAllConf_Product()
    {
        try
        {
            var db = new DBHelperTest();
            var dtResult = db.GetAllConf_ProductDataTable(); // 数据库查询

            // 直接赋值,触发DataTableUpdated事件
            ExistingProductionInfoDgvItemSource = dtResult ?? new DataTable();
        }
        catch (Exception ex)
        {
            CustomMessageBoxView.ShowAsync("数据加载失败", $"错误:{ex.Message}");
        }
    }

    #endregion

2.3代码后置

cs 复制代码
    private ProductSettingViewModel _vm;

    public ProductSetting()
    {
        this.DataContext = new ProductSettingViewModel();

        InitializeComponent();

        this.PointerReleased += ProductSetting_OnPointerReleased;


        // 1. 绑定ViewModel
        // this.DataContext = new ProductSettingViewModel();
        _vm = new ProductSettingViewModel();
        DataContext = _vm;

        // 2. 订阅事件-执行列生成
        ExistingProductionInfoDgv.Loaded += ExistingProductionInfoDgv_Loaded;
    }

    #region 现有产品信息Dgv1生成列

    // 3. DataGrid加载完成后自动触发(核心:此时DataGrid一定非null)
    private void ExistingProductionInfoDgv_Loaded(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
    {
        // 订阅ViewModel的数据更新事件(数据就绪后生成列)
        _vm.DataTableUpdated += Vm_DataTableUpdated;

        // 初始数据生成:如果ViewModel已查询到数据,直接生成列
        if (_vm.ExistingProductionInfoDgvItemSource?.Rows.Count > 0)
        {
            GenerateColumns(_vm.ExistingProductionInfoDgvItemSource);
        }
    }

    // 4. 生成列的核心方法(仅View层处理,完全对应示例逻辑)
    private void GenerateColumns(DataTable dt)
    {
        // 清除旧列
        ExistingProductionInfoDgv.Columns.Clear();

        // 绑定数据源为DataView
        ExistingProductionInfoDgv.ItemsSource = dt.DefaultView;

        var columnNameMap = new Dictionary<string, string>
        {
            { "ID", "序号" },
            { "Name", "产品名称" },
            { "Code", "产品识别码" },
            { "SOP_BarcodeParam", "产品扫码参数" },
            { "SOP_PartParam", "零件追溯参数" },
            { "SOP_WorkParam", "工序作业参数" },
            { "ProgramNum", "图号识别起始位" },
            { "StartNum", "图号识别位数" },
            { "CodeNum", "产品型号" },
            { "OrderProductionCode", "生产用号" }
            // 后续需要添加其他字段映射,直接在这里加键值对即可
        };

        // 遍历列生成DataGrid列
        foreach (DataColumn col in dt.Columns)
        {
            // 3. 根据字段名获取显示名(如果没有匹配的映射,默认用原字段名)
            string displayHeader = columnNameMap.TryGetValue(col.ColumnName, out string name)
                ? name
                : col.ColumnName;

            DataGridColumn gridCol = col.DataType == typeof(bool)
                ? new DataGridCheckBoxColumn //创建复选框单元格
                {
                    Header = displayHeader,
                    Binding = new Binding($"Row.ItemArray[{col.Ordinal}]")
                }
                : new DataGridTextColumn //创建文本框单元格
                {
                    Header = displayHeader,
                    Binding = new Binding($"Row.ItemArray[{col.Ordinal}]")
                };

            ExistingProductionInfoDgv.Columns.Add(gridCol);
        }
    }

    // 5. 响应ViewModel的数据更新(数据变化时重新生成列)
    private void Vm_DataTableUpdated(object? sender, DataTable dt)
    {
        GenerateColumns(dt);
    }

    #endregion

3.效果

显示成功

4.修改

4.1过滤不需要的列

某一个表:

其中FieldName和FieldAttribute 是我不需要的数据库字段

在生成列的方法中:使用HashSet设定一组需要的列名,

// 1. 定义需要显示的列名(仅保留这三个)

var needShowColumns = new HashSet<string>

{

"ID",

"FieldDesc",

"FieldDataSource"

};

在声明列前使用if判断是否是需要的列即可

复制代码
// 过滤不需要的列
if (!needShowColumns.Contains(col.ColumnName))
{
    continue; // 不生成该列,直接进入下一次循环
}
cs 复制代码
  private void ProductSettingDgv_GenerateColumns(DataTable dt)
    {
        ProductSettingDgv.Columns.Clear();

        ProductSettingDgv.ItemsSource = dt.DefaultView;

        // 1. 定义需要显示的列名(仅保留这三个)
        var needShowColumns = new HashSet<string>
        {
            "ID",
            "FieldDesc",
            "FieldDataSource"
        };

        var columnNameMap = new Dictionary<string, string>()
        {
            { "ID", "序号" },
            { "FieldDesc", "参数名称" },
            { "FieldDataSource", "参数设定值" },
        };

        //遍历生成DataGrid列
        foreach (DataColumn col in dt.Columns)
        {
            // 过滤不需要的列
            if (!needShowColumns.Contains(col.ColumnName))
            {
                continue; // 不生成该列,直接进入下一次循环
            }

            //根据数据库字段名,获取,Dgv2的列名
            string displayHeader = columnNameMap.TryGetValue(col.ColumnName, out string name)
                ? name
                : col.ColumnName;
            //判断列的类型 ?复选框:文本

            DataGridColumn gridcol = col.DataType == typeof(bool)
                ? new DataGridCheckBoxColumn
                {
                    Header = displayHeader,
                    Binding = new Binding($"Row.ItemArray[{col.Ordinal}]")
                }
                : new DataGridTextColumn
                {
                    Header = displayHeader,
                    Binding = new Binding($"Row.ItemArray[{col.Ordinal}]")
                };
            ProductSettingDgv.Columns.Add(gridcol);
        }
    }
相关推荐
翔云 OCR API15 小时前
发票查验接口详细接收参数说明-C#语言集成完整示例-API高效财税管理方案
开发语言·c#
虫小宝16 小时前
高佣金的返利平台性能压测:从单接口到全链路的性能瓶颈分析
c#·linq
故事不长丨17 小时前
C#集合:解锁高效数据管理的秘密武器
开发语言·windows·c#·wpf·集合·winfrom·字典
jghhh0118 小时前
基于C#实现与三菱FX系列PLC串口通信
开发语言·算法·c#·信息与通信
故事不长丨18 小时前
C#队列深度剖析:解锁高效编程的FIFO密码
visualstudio·c#·wpf·多线程·winfrom·队列·queue
bugcome_com19 小时前
C# 反射(Reflection)超全解析
c#
bjzhang7521 小时前
Dorisoy.AMS--一款采用C# WinForm框架+SQLite数据库的企业/机构资产管理解决方案
sqlite·c#·资产管理
零度@1 天前
Java消息中间件-Kafka全解(2026精简版)
java·kafka·c#·linq
leiming61 天前
c++ QT 开发第二天,用ui按钮点亮实体led
开发语言·qt·ui
2501_941882481 天前
在开普敦跨区域部署环境中构建高可靠分布式配置中心的设计思路与实现实践
开发语言·c#