LINQPad.Controls Event sender got null

// Winform
var button = new System.Windows.Forms.Button {
  Text = "Copy",
  Location = new Point(150, 100),
  Size = new Size(100, 30)
};

button.Click += (sender, e) => {
  //here can got button object
  var buttonSender = (sender as System.Windows.Forms.Button);    
};

// LINQPad.Controls
var button = new LINQPad.Controls.Button("Copy").Dump();
button.Click += (sender, e) => {
  // this got null
  var buttonSender = (sender as LINQPad.Controls.Button);    
};

Why transform sender to LINQPad.Controls always got null

Comments

  • i2van
    edited January 2025
    var button = new LINQPad.Controls.Button("Copy").Dump();
    button.Click += (sender, e) => {
      var buttonSender = sender.GetType().Dump();
    };
    

    LINQPad.Controls.Core.HtmlElement

  • Good spot. This is not ideal behavior - LINQPad should supply the button as the sender, not the HtmlElement. Fixing it is a breaking change, though, so it might have to wait for LINQPad 9.

  • @JoeAlbahari said:
    Good spot. This is not ideal behavior - LINQPad should supply the button as the sender, not the HtmlElement. Fixing it is a breaking change, though, so it might have to wait for LINQPad 9.

    Is this issue fixed in LINQPad 9?

  • It didn't pass review because that change that would still break existing scripts.

    Is there any reason that you need this? The sender parameter was useful in the C# 1 days, before the language had closures. But now we can do this (which is also type-safe):

    var button = new LINQPad.Controls.Button("Copy").Dump();
    button.Click += (sender, e) => {
      var buttonSender = button;
    };
    
  • in some case,winform can set multiple button click event use same method,and identify triggered by whitch button inside the function

    var btn1 = new Button { Text = "btn1" };
    btn1.Click += Btn_Click;
    
    var btn2 = new Button { Text = "btn2" };
    btn2.Click += Btn_Click;
    
    var btn3 = new Button { Text = "btn3" };
    btn3.Click += Btn_Click;
    
    
    private void Btn_Click(object? sender, EventArgs e) {
      var btn = sender as Button;
    
      // do something no matter which button was clicked
    
      switch (btn?.Text) {
        case "btn1":
          // Handle btn1 click event
          break;
        case "btn2":
          // Handle btn2 click event
          break;
        case "btn3":
          // Handle btn3 click event
          break;
        default:
          break;
      }
    }
    
  • If you are just looking at the text, you could cast sender as HtmlElement and then look at InnerText.

    If you need sender to be the Button, you could define the click event in the constructor. (You do loose the EventArgs argument)

    void Main()
    {
        var btn1 = new Button("btn1", (b) => Btn_Click1(b)).Dump();
    
        var btn2 = new Button("btn2").Dump();
        btn2.Click += Btn_Click2;
    }
    
    private void Btn_Click1(object? sender)
    {
        var btn = sender as Button ;
        Util.ToExpando(btn).Dump();     
        btn?.Text.Dump();
    }
    
    private void Btn_Click2(object? sender, EventArgs e)
    {
        var element = sender as LINQPad.Controls.Core.HtmlElement;
        Util.ToExpando(element).Dump();
        element?.InnerText.Dump();
    }