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, ValueChanged etc) that is triggered that does something but my main quesiton is this:
What I want to do is run a single method which will update a text field on my form but currently I have it just repeated 24 times. This works but I feel there must be a better way ... Below is an example of what I have so far.
private void button3_Click(object sender, EventArgs e)
{
// Code Specific to the Buton3_Click
UpdateTextLabel();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
// Code Specific to the checkBox1_CheckChanged
UpdateTextLabel();
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
// numericUpDown1 specific code ....
UpdateTextLabel();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// comboBox1 specific stuff ...
UpdateTextLabel();
}
// .... and so on for every method ....
Is there a better way to achieve this? I want to say "if any control is clicked or changed ... DO THIS "UpdateTextLabel()" thing " but not sure how to go about it. Happy to be directed to the answer as the questions I typed into search didn't seem to be the "right questions" ...
Thanks!
yes, any events of any controls can share the same event handler method as long as their event handler delegates are the same, in this case, the event handler delegates of those controls are all of type "EventHandler" (no return value and 2 arguments: object sender and EventArgs e).
Yes, you don't want to write code like this. You don't have to, the Application.Idle event is ideal to update UI state. It runs every time after Winforms retrieved all pending messages from the message queue. So is guaranteed to run after any of the events you currently subscribe. Make it look like this:
For sure! You can use lambdas to easily deal with the unused arguments:
Or as some developers are trending, if you don't care about the args, you can use underscores to "ignore" them for readability:
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:
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 requireUpdateTextLabel
to fire afterSubmitForm
)Or you can move the
UpdateTextLabel
call into your button handler: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: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):
So even though we do not explicitly make a call anywhere to
Rebind()
, the attribute and Aspect Oriented Programming ends up running that extra codeOnSuccess
there whenever the method is invoked successfully.