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);
        }
    }
相关推荐
七七墨染2 小时前
DotMemory系列:5. 如何实现自动化抓取和应用自托管
运维·c#·自动化
周周爱喝粥呀2 小时前
UI设计原则和Nielsen 的 10 条可用性原则
前端·ui
王家羽翼-王羽3 小时前
C# 连接 PLC 的S7西门子协议读写,样例分享
c#
斯内科4 小时前
C#进行CAN【控制器局域网】通讯
c#·can·pcanbasic.net
张人玉6 小时前
C#WPF——MVVM框架编写管理系统所遇到的问题
开发语言·c#·wpf·mvvm框架
马达加斯加D6 小时前
C# --- 如何写UT
前端·c#·log4j
Charles_go6 小时前
C#中级39、什么是依赖注入设计模式
java·设计模式·c#
eggcode7 小时前
C#开源库ACadSharp将Dwg转Dxf
c#·dxf·dwg
拼好饭和她皆失8 小时前
C#学习入门
开发语言·学习·c#
小小编程能手9 小时前
大小端字节序
c#