C# 自定义特性实现 DataGridView 全自动列生成

37 阅读3分钟

前言

在 WinForm 开发中,DataGridView 是一个非常常用的控件,用于展示结构化数据。然而,当面对列数较多、字段频繁变动的场景时(如配方管理、配置系统等),手动设置每一列不仅效率低下,还容易出错。

本文将介绍一种基于 C# 自定义特性(Custom Attribute) 实现 DataGridView 列动态生成的方法,通过实体类属性特性的描述信息,自动添加表格列结构,从而提高开发效率和维护性。

正文

1、创建窗体应用

首先,在 Visual Studio 中创建一个 Windows Forms 应用程序项目。在主窗体中拖入以下控件:

  • 一个 DataGridView 控件(命名为 dgvMain

  • 一个按钮(命名为 btn_Generate

同时,为了确保列由代码控制,取消勾选 DataGridView 的"启用添加"、"启用编辑"、"启用删除"功能。

2、定义实体类与自定义特性

我们创建一个名为 Points 的实体类,并为其每个属性添加自定义特性,用于指定该列的显示名称和宽度。

[AttributeUsage(AttributeTargets.Property)]
public class CustomAttribute : Attribute
{
    public string DisplayName { get; set; }
    public int DisplayWidth { get; set; }

    public CustomAttribute(string displayName, int displayWidth)
    {
        DisplayName = displayName;
        DisplayWidth = displayWidth;
    }
}

public class Points
{
    [CustomAttribute("站点编号", 100)]
    public string StationNo { get; set; }

    [CustomAttribute("参数1", 80)]
    public int TD_P1 { get; set; }

    [CustomAttribute("参数2", 80)]
    public int TD_P2 { get; set; }
}

3、初始化 DataGridView 方法

接下来,编写一个方法 InitialDataGridView(),它会通过反射读取 Points 类的属性及其特性信息,动态生成 DataGridView 的列。

private void InitialDataGridView()
{
    Type t = typeof(Points);
    foreach (PropertyInfo pi in t.GetProperties())
    {
        // 获取属性名称
        string propertyName = pi.Name;
        // 获取显示文本
        string displayName = pi.GetCustomAttribute<CustomAttribute>()?.DisplayName;
        // 获取显示宽度
        int displayWidth = pi.GetCustomAttribute<CustomAttribute>().DisplayWidth;

        DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn()
        {
            HeaderText = displayName,
            Width = displayWidth,
            DataPropertyName = propertyName,
            SortMode = DataGridViewColumnSortMode.NotSortable,
            AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet
        };

        this.dgvMain.Columns.Add(column);
    }
}

在窗体构造函数中调用此方法,并禁用自动列生成功能:

public FrmMain()
{
    InitializeComponent();
    this.dgvMain.AutoGenerateColumns = false;
    InitialDataGridView();
}

4、按钮点击生成数据源

为按钮添加点击事件,生成测试数据并绑定到 DataGridView

private void btn_Generate_Click(object sender, EventArgs e)
{
    List<Points> points = new List<Points>();
    for (int i = 1; i < 10; i++)
    {
        points.Add(new Points()
        {
            StationNo = "站点" + i,
            TD_P1 = 123,
            TD_P2 = 456,
        });
    }
    this.dgvMain.DataSource = null;
    this.dgvMain.DataSource = points;
}

5 、效果展示

运行程序后,点击"生成数据"按钮,效果如下图所示:

可以看到,列标题、宽度均已根据自定义特性正确显示,且无需手动修改 UI 界面。

总结

通过本方案,可以实现以下优势:

  • 自动化列生成:只需在实体类中添加特性,即可动态生成 DataGridView 列。

  • 高可维护性:当业务字段发生变化时,只需修改实体类,无需重新设计界面。

  • 适用于复杂场景:特别适合字段多、变化频繁的应用场景,如配方系统、参数配置表等。

  • 代码结构清晰:将数据模型与界面解耦,提升代码的可读性和扩展性。

总结

本文介绍了如何利用 C# 的反射机制与自定义特性,实现 DataGridView 的全自动列生成。

这种方法不仅提高了开发效率,也增强了系统的灵活性和可维护性,是处理动态列结构的一种实用解决方案。

对于需要频繁调整列结构或数据模型不断演化的 WinForm 项目来说,这种基于特性的动态列生成方式具有很高的参考价值。

关键词

DataGridView、自定义特性、反射、WinForm、数据绑定、动态列生成、实体类、C#、UI 自动化、配方管理

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!