WinForm C# 如何将方法附加到以编程方式创建的控件

WinForm C# how attach an Method to a Control programmaticaly created

在我的应用程序中,我以编程方式生成了一堆 DataGridView。我可以向它添加 add/remove 行并从中检索所有数据并将数据复制到另一个 DataGrid 中。

例如我创建它的时候

public void Example(TabControl tab)
        for(int i=0;i<tab.TabCount;i++)
        {
        tab.TabPages.Add("Panneau " + tab.TabCount);
        
        DataGridView panGridView = new DataGridView();
        panGridView.Name = "panGridView_" + tab.TabCount;
        panGridView.Location = new System.Drawing.Point(0, 0);
        panGridView.RowTemplate.Height = 24;
        panGridView.Size = new System.Drawing.Size(1375, 458);
        panGridView.Columns.Add("id", "id");
        panGridView.Columns.Add("part_code", "part_code");
        panGridView.Columns[0].Width = 100;
        panGridView.Columns[1].Width = 150;
        panGridView.Visible = true;
        panIndex.Items.Add(tab.TabCount - 1);
        tab.TabPages[tab.TabCount - 1].Controls.Add(panGridView);

        }

现在,我想将方法​​附加到此控件。我认为最好的方法是在初始化控件时附加它。例如,我会附加一个像这样的方法

public void Action(DataGridViewCellMouseEventArgs e)
{
 if(e.RowIndex==2)
 {
  MessageBox.Show("Hello");
 }

我试了很多,但不知道怎么做。

谢谢

如@CurleD 所述,您只需将您的方法订阅到特定的 EventHandler。因此,将您的 Action 更改为:

private void panGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if(e.RowIndex==2)
    {
        MessageBox.Show("Hello");
    }
}

然后订阅CellMouseClick事件:

panGridView.CellMouseClick += panGridView_CellMouseClick;

在我看来,您需要一种特殊的 DataGridView。您想要一个带有附加方法的 DataGridView。您已经了解到,每当您需要一个“class,与另一个 class 非常相似,但只有一点点不同”时,您需要创建一个派生的 class,或者创建一个composition,如果你不想暴露基类的所有方法 class.

class DataGridViewWithAttachedMethod : DataGridView   // TODO: invent proper name
{
    ...
}

class MySpecialDataGridView : UserControl
{
    private DataGridView dgv1;

    ...
}

第一种方法的优点是你的class(=代码,不是操作符)的用户可以访问所有的DataGridView方法,所以使用起来会非常灵活。缺点:他们可以访问所有 DataGridView 方法,因此他们可能会弄乱您的 DataGridView。

您是使用推导还是组合取决于您的 class 需要多简单,换句话说:您是否想公开您不希望被其他人使用的方法?

I want to attach Method to this Control.

这个不是很清楚。你想给 DataGridView 一个额外的方法,总是一样的吗?或者您想动态附加一个方法:dgv1 有另一个附加方法而不是 dgv2。

class DgvWithExtraMethod : ...
{
    public void Action(DataGridViewCellMouseEventArgs e)
    {
        if(e.RowIndex==2)
        {
             MessageBox.Show("Hello");
        }
    }
}

此 dgv 的所有实例都将具有相同的额外方法。你所要做的就是创建一个这个class的对象,你就会有这个方法

但是,如果您想将不同的方法附加到 class 的实例,您需要一个包含此方法的 属性。

class DgvWithMethod : ...
{
    public Action<DataGridViewCellMouseEventArgs> ExtraMethod {get; set;}
}

如果您想要 class 万无一失,请考虑使用“无操作 (NOP)”初始化该方法

private static Action<DataGridViewCellMouseEventArgs> NOP = (e) => {};

public Action<DataGridViewCellMouseEventArgs> ExtraMethod {get; set;} = NOP;

用法:

DgvWithMethod dgv1 = new DgvWithMethod
{
    ExtraMethod = (e) =>
    {
        if(e.RowIndex==2)
        {
             MessageBox.Show("Hello");
        }
    }
}

这就是您问题的确切答案。但是,我想你想知道的是:如果操作员点击第 2 行,那么我想执行方法 F(),如果他点击第 3 行,我想执行方法 G()

如果这是您想要的,请使用 visual studio 设计器在 DataGridView.CellMouseClick, or if you want to reuse this class (derivation / composition) override DataGridView.OnCellMouseClick 上添加事件处理程序。

private void DataGridView1_CellMouseClick(Object sender,
    DataGridViewCellMouseEventArgs e)
{
    // find out which column is clicked
    switch (e.ColumnIndex)
    {
        case 0: // column Id clicked
            this.ProcessColumnIdClick(e);
            break;
        case 1: // column Name clicked
            this.ProcessColumnNameClick(e);
            break;
        ...

不过请注意:如果您允许列重新排序,您应该将 ColumnIndex 与每列的 DisplayIndex 进行比较。

if (e.ColumnIndex == this.columnId.DisplayIndex)
    this.ProcessColumnIdClick(e);
else if (e.ColumnIndex == this.columnName.DisplayIndex)
    ...