Search code examples
c#winformslambdaref

Generic CheckBox Creator function adding anonymous event handlers with referenced property


I want to create a bunch of simple checkboxes for a Windows from and have them change bools. Because it is a lot of them, I thought I could skip writing a bunch of CheckedChanged handlers and have a generic "Creator" function like this

    static CheckBox CreateCheckBox(ref bool binding, string name)
    {
        var box = new CheckBox();
        box.Checked = binding;
        box.CheckedChanged += (object sender, EventArgs e) => { binding = !binding; };
        box.Text = name;
        return box;
    }

And Then create my boxes like:

ParentForm.Controls.Add(CreateCheckBox(ref prop1, nameof(prop1));
ParentForm.Controls.Add(CreateCheckBox(ref prop2, nameof(prop2));
.....

I obviously got the "Can't use ref in a lambda expression or anonymous function". I read up on it and it makes sense. But is there a way to have this sort of simple creator function that that generically adds the handlers?

I know there would be an issue here with never removing the handler but this is for a debug mode feature that is only used by developers to debug and improve very specific.algorithm. Maybe I am just being lazy to write and add all the handlers but I also just felt cleaner.


Solution

  • You do not need to pass anything by reference, use one of the following options:

    1. Pass a getter Func and a setter Action
    2. Setup databinding

    Example 1 - Pass a getter Func or a setter Action

    Pass the getter and setter as func/action:

    public CheckBox CreateCheckBox(string name, Func<bool> get, Action<bool> set)
    {
        var c = new CheckBox();
        c.Name = name;
        c.Text = name;
        c.Checked = get();
        c.CheckedChanged += (obj, args) => set(!get());
        return c;
    }
    

    And use it like this, for example:

    CreateCheckBox("checkBox1", () => textBox1.Enabled, (x) => textBox1.Enabled = x);
    CreateCheckBox("checkBox2", () => textBox2.Enabled, (x) => textBox2.Enabled = x);
    

    Example 2 - Setup databinding

    What you are trying to implement is what you can achieve by setting up data binding:

    public CheckBox CreateCheckBox(string name, object dataSource, string dataMember)
    {
        var c = this.Controls[name] as CheckBox;
        c.Name = name;
        c.Text = name;
        c.DataBindings.Add("Checked", dataSource,
            dataMember, false, DataSourceUpdateMode.OnPropertyChanged);
        return c;
    }
    

    And use it like this:

    CreateCheckBox("checkBox1", textBox1, "Enabled");
    CreateCheckBox("checkBox2", textBox2, "Enabled");