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);
        }
    }
相关推荐
左手吻左脸。4 小时前
Element UI表格中根据数值动态设置字体颜色
vue.js·ui·elementui
R-G-B5 小时前
【02】大恒相机SDK C#开发 —— 初始化相机,采集第一帧图像
c#·大恒相机sdk·大恒相机初始化·大恒相机采集图像
韩立学长7 小时前
【开题答辩实录分享】以《制造型企业供应商档案管理系统设计与开发》为例进行答辩实录分享
sqlserver·c#
我的xiaodoujiao7 小时前
从 0 到 1 搭建 Python 语言 Web UI自动化测试学习系列 8--基础知识 4--常用函数 2
前端·python·测试工具·ui
我命由我123459 小时前
Photoshop - Photoshop 工具栏(10)透视裁剪工具
经验分享·笔记·学习·ui·职场和发展·职场发展·photoshop
ziyue75759 小时前
vue修改element-ui的默认的class
前端·vue.js·ui
我都学杂了。。。11 小时前
Python的循环技巧与性能优化实战
ui
ajassi200012 小时前
开源 C# 快速开发(十七)进程--消息队列MSMQ
windows·开源·c#