在事件中定义参数

时间:2013-06-28 12:38:35

标签: c# button event-handling

我有一个带行的TableLayoutPanel(tlp)。我用一个按钮手动添加行。我在最后一行下面创建的每一行都有一个按钮,可以从tlp中删除该行。这是代码:

    private void btnTSatirEkle_Click(object sender, EventArgs e)
    {
        tlpTDersRows = tlpTDers.RowCount;

        tlpTDers.RowCount++;

        DateTimePicker dtp = new DateTimePicker();
        dtp.Name = "dtpTR" + (tlpTDersRows).ToString();
        DateTimePicker dtp2 = (DateTimePicker)tlpTDers.Controls["dtpTR" + (tlpTDersRows - 1).ToString()];
        dtp.Value = dtp2.Value.AddDays(1);
        dtp.Dock = DockStyle.Fill;
        tlpTDers.Controls.Add(dtp, 0, tlpTDersRows);

        ComboBox comb = new ComboBox();
        comb.Name = "cbxTR" + (tlpTDersRows).ToString();
        comb.Dock = DockStyle.Fill;
        comb.Items.AddRange(devamDur);
        tlpTDers.Controls.Add(comb, 1, tlpTDersRows);

        TextBox txtr = new TextBox();
        txtr.Name = "txtTR" + (tlpTDersRows).ToString();
        txtr.Dock = DockStyle.Fill;
        txtr.Multiline = true;
        tlpTDers.Controls.Add(txtr, 2, tlpTDersRows);

        oldX = btnTSatirEkle.Location.X;
        oldY = btnTSatirEkle.Location.Y;

        Button buttonNew = new Button();
        buttonNew.Name = "btnDelTR" + (tlpTDersRows - 1).ToString();
        buttonNew.Text = "-";
        buttonNew.Location = new Point(oldX, oldY);
        buttonNew.Size = btnTSatirEkle.Size;
        this.Controls.Add(buttonNew);
        buttonNew.Click += new EventHandler(SatirSil);  //I get error here, even I write SatirSil(sender, e, tlpTDersRows - 1)..

        btnTSatirEkle.Location = new Point(644, tlpTDers.Controls["dtpTR" + tlpTDersRows.ToString()].Location.Y + 12);

        tlpTDersRows++;
    }

    private void SatirSil(object sender, EventArgs e, int rowNo)
    {
       //codes
    }

我想将行号作为参数发送给SatirSil方法(当我点击buttonNew_Click事件时会调用它。)

有什么想法吗?

6 个答案:

答案 0 :(得分:2)

变化:

buttonNew.Click += new EventHandler(SatirSil);

buttonNew.Click += new EventHandler((snd, ev)=>SatirSil(snd,ev,rowno));

或使用您自己的变量(即tlpTDersRows),它可能是这样的:

buttonNew.Click += new EventHandler((snd, ev)=>SatirSil(snd,ev,tlpTDersRows-1));

答案 1 :(得分:2)

Button.Click事件定义为

public event EventHandler Click

其中EventHandler

定义
public delegate void EventHandler(Object sender, EventArgs e);

这意味着对于可分配为事件处理程序的方法,它必须具有委托定义的确切签名,即它必须采用两个参数:objectEventArgs实例,它必须返回void。您SatirSil方法的签名

void SatirSil(object sender, EventArgs e, int rowNo)

不匹配,因为它有一个额外的整数参数。如其他答案中所述,您有两个常见的解决方案:

  • 以某种方式将额外参数嵌入sender参数中,因为EventArgs本身几乎没用。由于大多数时候sender参数实际上都是Control对象,因此通常使用Control.Tag属性来存储有关发送方的额外数据,这些数据将由处理程序取出并使用按要求。这看起来像是:

    Button buttonNew = new Button();
    ...
    buttonNew.Tag = (tlpTDersRows - 1);
    buttonNew.Click = SatirSil;
    ....
    void SatirSil(object sender, EventArgs e)
    {
       int rowNumber = (int)(sender as Control).Tag;
       //rest of code
    }
    
  • 以某种方式创建一个特殊版本的处理程序,其行号为“硬编码”。从C#3.0开始,使用lambda语法相对容易实现,它为您生成内联“方法”,例如。

    EventHandler handler = (sender, e) => {...code here ...}
    

    是一个代码,用于创建一个名为“handler”的委托实例,您可以使用

    将其附加到事件
    someButton.Click += handler;
    

    或者您甚至可以使用

    调用
    handler(senderValue, eValue); 
    

    请注意,“... here here ...”块仍包含在您编写声明的原始方法中,因此该方法可访问的任何内容都可供lambda表达式的主体访问。知道您可以使用以下代码为每个按钮创建单独的处理程序:

    Button buttonNew = new Button();
    ...
    buttonNew.Click = (_, __) => SatirSil(rowNumber);
    //if you do not care about parameters, 
    //it's customary to use _, __,  etc for the names
    //instead of the more verbose
    //buttonNew.Click = (sender, e) => SatirSil(rowNumber);
    ....
    void SatirSil(int rowNumber)
    {
       //actual implementation
    }
    

我个人更喜欢第二种选择,因为它巧妙地将与创建和连接按钮有关的代码与执行实际工作的代码分开。例如,如果代码的另一部分需要SatirSil方法,则调用将分别为:

Control dummy = new Control();
dummy.Tag = myRowNumber;
SatirSil(dummy, null);

VS

SatirSil(myRowNumber);

答案 2 :(得分:1)

我有一个想法:

buttonNew.Click += new EventHandler((sender,args)=>SatirSil(sender,args,rowNo));

这样您仍然可以使用兼容的buttonNew.Click设置EventHandler,但匿名方法的主体将使用您的方法SatirSil,该方法使用您的行号作为参数

答案 3 :(得分:1)

该按钮是您活动的sender。因此,如果您将行号存储在按钮的Tag属性中,请执行以下操作:

buttonNew.Tag = tlpTDersRows;
然后,您可以执行以下操作:

private void SatirSil(object sender, EventArgs e)
{
    Button button = (Button)sender;
    int rowNo = (int)button.Tag;
    // ... delete row here.
}

答案 4 :(得分:0)

怎么样:

Button buttonNew = new Button();
buttonNew.Name = "btnDelTR" + (tlpTDersRows - 1).ToString();
buttonNew.Text = "-";
buttonNew.Location = new Point(oldX, oldY);
buttonNew.Size = btnTSatirEkle.Size;
this.Controls.Add(buttonNew);
buttonNew.Tag = tlpTDersRows - 1;
buttonNew.Click += SatirSil;

private void SatirSil(object sender, EventArgs e)
{
   //codes
   var btn = (Button)sender;
   var row = (int)btn.Tag;

}

答案 5 :(得分:0)

您无法修改已经定义的Button click事件的delgate签名。如果您正在尝试执行此操作,则会出现编译器错误。 如何以其他方式实现,在创建按钮名称时,将其附加行号,以便在事件处理程序中将发送方对象强制转换为按钮并获取名称并从中提取行号。

    buttonNew.Name = "btnDelTR_" + rowNumber

    private void SatirSil(object sender, EventArgs e, int rowNo)
    {
             int rowNo =   //split the string to get the number.
    }