1

Briefly, my app adds checkboxes programmatically into a flowlayoutpanel named "fp".

fp.Controls.Add(new CheckBox() { Name = "cb1", Text = "New Checkbox", Checked = true, AutoSize = true, AllowDrop = true });

i'm stuck trying to add a mouseclick event inside that new Checkbox instance. I tried adding the line below into the code above.

this.MouseDown += new MouseEventHandler(cbox_MouseDown);

But I get Invalid initializer member declarator

I also tried to add this:

((CheckBox)(this.Controls.Find("cb1", false))[0]).MouseDown += new MouseEventHandler(cbox_MouseDown);

before adding the new checkbox instance but it does not work either.

I could highly appreciate a way to insert the event directly into the new CheckBox() instance .

Thank you guys <3

MrJack Mcfreder
  • 692
  • 1
  • 10
  • 21
  • 1
    Please post a multi-line code example where you tried to do `this.MouseDown += new MouseE...` because your post is unclear about how you did it. Obviously putting it on the line below `fp.Controls.Add` isn't going to work because `this` is _not_ the `CheckBox`. – Dai Nov 27 '21 at 14:14
  • Also, you should use `Click` instead of `MouseDown`. This is because `MouseDown` is only raised when Windows detects an actual physical mouse button press, whereas the `Click` event is raised when the user toggles a checkbox using alternative means, such as tapping the space-bar when the checkbox has focus. The same applies to `Button.Click` too. (Fun fact: `CheckBox` **is** actually a Button: `class CheckBox : ButtonBase`). – Dai Nov 27 '21 at 14:19
  • Are you asking how to use the "Object and Collection Initializers" syntax to contextually set the event handler on the newly created CheckBox? Are you not able to use a CheckBox variable? – Steve Nov 27 '21 at 14:28
  • 1
    The code added the box to the FlowLayoutPanel, searching the *form's* controls is not going to find it. So either this.Controls.Find("cb1", true) or the more sensible fp.Controls.Find("cb1", false). Or the ultimately sensible var box = new Checkbox() {...} so you can simply use box.MouseDown += – Hans Passant Nov 27 '21 at 14:51

1 Answers1

2
  • C#'s Object-Initializer syntax does not support events.
    • C#'s Object-Initializers have a lot of other shortcomings too, I'm not a fan of them (horrible debugging, broken line-numbers in stack-traces, it ignores IDisposable when an exception is thrown, you can't use it with an existing object, often takes up more lines-of-code than otherwise, etc).
  • However, you can define a new extension-method for ControlsCollection which will add the event-handler for you.

Like so:

MyExtensions.cs:

public static class MyExtensions
{
    public static void AddWithClickHandler( this ControlsCollection ctrls, EventHandler onClickHandler, CheckBox newCheckBox )
    {
        newCheckBox.Click += onClickHandler;
        ctrls.Add( newCheckBox );
    }
}

MyForm.cs:

public partial class MyForm : Form
{
    private readonly EventHandler onClickHandler;

    public MyForm()
    {
        this.InitializeComponent();

        //

        this.onClickHandler = new EventHandler( this.cbox_MouseDown );
    }

    private void cbox_MouseDown( Object sender, EventArgs e )
    {
        // 
    }
    
    private Int32 checkboxCount = 0;
    private String GetNewCheckboxName()
    {
        this.checkboxCount += 1;
        return "cb" + this.checkboxCount.ToString("d");
    }

    public void AddCheckboxes()
    {
        this.fp.Controls.AddWithClickHandler( onClickHandler, new CheckBox() { Name = this.GetNewCheckboxName(), Text = "New Checkbox", Checked = true, AutoSize = true, AllowDrop = true } );

        this.fp.Controls.AddWithClickHandler( onClickHandler, new CheckBox() { Name = this.GetNewCheckboxName(), Text = "New Checkbox", Checked = true, AutoSize = true, AllowDrop = true } );

        this.fp.Controls.AddWithClickHandler( onClickHandler, new CheckBox() { Name = this.GetNewCheckboxName(), Text = "New Checkbox", Checked = true, AutoSize = true, AllowDrop = true } );
    }
}


Note that:

  • In my code, the MyForm class only ever creates a single EventHandler instance (using new EventHandler), this is important as you need to allow code to de-register (i.e. remove) event-handlers to prevent memory-leaks.
    • Unfortunately you cannot remove event-handlers registered using the shorthand syntax like this: obj.Click += this.OnClickMethod;
    • Nor can you remove event-handlers implemented as lambda-methods, e.g. obj.Click += ( obj, sender ) => this.DoSomething();
  • Control Names need to be unique, so rather than hardcoding strings like "cb1" and "cb2", unique names for each and every checkbox is generated by the GetNewCheckboxName() method.
Dai
  • 141,631
  • 28
  • 261
  • 374
  • 1
    Omg Dude! Exactly and literally what I needed. Why stuff like this I can never find in MSDN or Google.. It's ok for me to register a single event and not be able to remove it. Thank you so much Dai! Marked as answer and +1. – MrJack Mcfreder Nov 27 '21 at 15:22