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);
        }
    }
相关推荐
精神小伙就是猛27 分钟前
C# sealed密封 追本溯源
开发语言·c#
雨季6662 小时前
C 语言学习指南:从入门到实战的系统路径
c#
yuegu7772 小时前
DevUI Modal 模态弹窗组件使用详解
ui·前端框架
少年张二狗4 小时前
Vue + Element-UI 图片上传实现拖拽排序功能
前端·vue.js·ui
sailing-data5 小时前
【UI Qt】入门笔记
开发语言·qt·ui
缺点内向5 小时前
如何在 C# 中创建、读取和更新 Excel 文档
c#·.net·excel
c#上位机5 小时前
halcon创建对象数组——concat_obj
图像处理·计算机视觉·c#·halcon
周杰伦fans6 小时前
Solidworks 二次开发模板SwCSharpAddin
c#
czhc11400756636 小时前
c# winform1212
java·javascript·c#
花北城6 小时前
【C#】DbToLinq多表连接
开发语言·c#