【问题标题】:define a parameter in event在事件中定义一个参数
【发布时间】:2013-06-26 05:45:20
【问题描述】:

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

    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 事件时将调用该方法)。

有什么想法吗?

【问题讨论】:

    标签: c# button event-handling


    【解决方案1】:

    变化:

    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));
    

    【讨论】:

    • 我尝试了您的解决方案,但我收到关于 (sender, e) 的错误。完整的消息如下:不能在此范围内声明名为“sender”的局部变量,因为它会给出不同的含义到“发件人”,它已经在“父级或当前”范围内用于表示其他内容..
    • @SertanPekel 例如,尝试将单词 sender 更改为 snd。我会更新我的代码。
    • @SertanPekel 发送者和 e 实际上与初始化事件的 btnTSatirEkle_Click 参数内的发送者冲突。因此,这就是为什么您必须将其名称更改为其他名称,以免发生冲突。在这种情况下,我使用 snd 作为发件人,使用 ev 作为事件来防止冲突。
    • 很高兴它为您工作@SertanPekel。快乐的编码和上帝保佑。
    【解决方案2】:

    Button.Click 事件定义为

    public event EventHandler Click
    

    EventHandler 定义为

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

    这意味着,对于一个可分配为事件处理程序的方法,它必须具有委托定义的确切签名,即它必须采用两个参数,一个object 和一个EventArgs 实例,并且它必须返回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); 
      

      请注意,“...code 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);
    

    对

    SatirSil(myRowNumber);
    

    【讨论】:

    • 我通过@Edper 的解决方案解决了这个问题,但您的回答包含很多可能对我有用的信息。非常感谢。
    【解决方案3】:

    我有一个想法:

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

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

    【讨论】:

      【解决方案4】:

      按钮是您的活动的sender。因此,如果您将行号存储在按钮的 Tag 属性中,如下所示:

      buttonNew.Tag = tlpTDersRows;
      

      你可以这样做:

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

      【讨论】:

        【解决方案5】:

        怎么样:

        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;
        
        }
        

        【讨论】:

          【解决方案6】:

          您无法修改已定义的 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.
              }
          

          【讨论】:

            猜你喜欢
            • 2015-02-12
            • 2021-04-25
            • 1970-01-01
            • 2016-09-27
            • 1970-01-01
            • 2017-04-26
            • 1970-01-01
            相关资源
            最近更新 更多