Can I assign a method to multiple Form-based Events?

前端 未结 3 1594
没有蜡笔的小新
没有蜡笔的小新 2021-01-21 03:31

I\'m constructing a Form and it has several numericUpDown controls, several checkbox controls and some text boxes etc. Each control has a event method (CheckedChanged, ValueCha

3条回答
  •  星月不相逢
    2021-01-21 04:28

    For sure! You can use lambdas to easily deal with the unused arguments:

    button3.Click += (sender, args) => UpdateTextLabel();
    checkBox1.CheckedChanged += (sender, args) => UpdateTextLabel();
    numericUpDown1.ValueChanged += (sender, args) => UpdateTextLabel();
    comboBox1.SelectedIndexChanged += (sender, args) => UpdateTextLabel();
    

    Or as some developers are trending, if you don't care about the args, you can use underscores to "ignore" them for readability:

    button3.Click += (_, __) => UpdateTextLabel();
    checkBox1.CheckedChanged += (_, __) => UpdateTextLabel();
    numericUpDown1.ValueChanged += (_, __) => UpdateTextLabel();
    comboBox1.SelectedIndexChanged += (_, __) => UpdateTextLabel();
    

    As the mighty Jon Skeet once schooled me, this is far superior to the default Visual Studio naming scheme of CONTROLNAME_EVENTNAME as you can easily read "when button 3 is clicked, update the text label", or "when the combobox is changed, update the text label". It also frees up your code file to eliminate a bunch of useless method wrappers. :)

    EDIT: If you have it repeated 24 times, that seems a bit odd from a design standpoint. ... reads again Oh darn. I missed the comments, you want to run specific code as well as update the text box. Well, you could register more than one event:

    button3.Click += (_, __) => SubmitForm();
    button3.Click += (_, __) => UpdateTextLabel();
    

    The problem with this, is technically, event listeners are not guaranteed to fire in-order. However, with this simple case (especially if you don't use -= and combine event handlers) you should be fine to maintain the order of execution. (I'm assuming you require UpdateTextLabel to fire after SubmitForm)

    Or you can move the UpdateTextLabel call into your button handler:

    button3.Click += (_, __) => SubmitForm();
    
    private void SubmitForm(object sender, EventArgs e)
    {
        //do submission stuff
        UpdateTextLabel();
    }
    

    Which kinda puts you into the same boat (albeit with better method naming). Perhaps instead you should move the UpdateTextLabel into a general "rebind" for your form:

    button3.Click += (_, __) => SubmitForm();
    
    private void SubmitForm(object sender, EventArgs e)
    {
        //do submission stuff
        Rebind();
    }
    
    private void Rebind()
    {
        GatherInfo();
        UpdateTextLabel();
        UpdateTitles();
    }
    

    This way if you have to do additional work besides just updating a text label, all your code is calling a general Rebind (or whatever you want to call it) and it's easier to update.

    EDITx2: I realized, another option is to use Aspect Oriented Programming. With something like PostSharp you can adorn methods to execute special code which gets compiled in. I'm 99% sure PostSharp allows you to attach to events (though I've never done that specifically):

    button3.Click += (_, __) => SubmitForm();
    
    [RebindForm]
    private void SubmitForm(object sender, EventArgs e)
    {
        //do submission stuff
    }
    
    [Serializable]
    public class RebindFormAttribute : OnMethodBoundaryAspect
    {
        public override void OnSuccess( MethodExecutionArgs args )
        {
            MyForm form = args.InstanceTarget as MyForm; //I actually forgot the "InstanceTarget" syntax off the top of my head, but something like that is there
            if (form != null)
            {
                form.Rebind();
            }
        }
    }
    

    So even though we do not explicitly make a call anywhere to Rebind(), the attribute and Aspect Oriented Programming ends up running that extra code OnSuccess there whenever the method is invoked successfully.

提交回复
热议问题