Event Handlers returning Values
By default most event handlers return void, however, it is possible for handlers to return values.
In a project you can have two events, a Save event that save data to the database and a Submit event that would send my data to another department. The Save event could be called from a Save button, while the Submit event was called from a Submit button.
When you trigger the Submit event, the event handler would trigger the Save event, and in case the save was successful, then it would submit the data. I needed the save to first validate my fields and only save the form if all fields passed validation.
Declaring Events
First you must declare the delegate with the type of value you want to return, in this case a bool. Then declare your custom event of the delegate type you defined.
1: #region Event Handler
2:
3: public delegate bool SaveEventHandler(object sender, System.EventArgs e);
4: public event SaveEventHandler Save;
5:
6: #endregion
Raising the Event
In order to raise the event we create a OnSave method that first checks if there are handlers associated with the Save event, if so, then raises the Save event.
1: #region OnSave
2:
3: /// <summary>
4: /// Raise Save Event
5: /// </summary>
6: /// <param name="e"></param>
7: /// <returns></returns>
8: private bool OnSave(EventArgs e)
9: {
10: bool _success = true;
11:
12: if( Save != null )
13: _success = Save(this, e);
14:
15: return _success;
16: }
17:
18: #endregion
Handlers are executed in the order they were associated.
When multiple handlers are associated with a single event in C# and the handler signature has a return type, then the value returned by the last handler executed will be the one returned to the event raiser.
1: #region Save Click
2:
3: /// <summary>
4: /// Save Button Event
5: /// </summary>
6: /// <param name="sender"></param>
7: /// <param name="e"></param>
8: private void btnSave_Click(object sender, System.EventArgs e)
9: {
10: OnSave(e);
11: }
12:
13: #endregion
1: #region btnSubmit_Click
2:
3: /// <summary>
4: /// Submit Button Event
5: /// </summary>
6: /// <param name="sender"></param>
7: /// <param name="e"></param>
8: private void btnSubmit_Click(object sender, System.EventArgs e)
9: {
10: if ( OnSave(e) )
11: {
12: //Submit Logic
13: }
14: }
15:
16: #endregion
Then we raise the event in our button click events handlers. The save button just save the data, for the submit button, saves the data, and if save was a successful submits the data.
Implementing the Event Handlers
First associate the event with a event handler, on page initialization.
1: EventSender sender = new EventSender();
2:
3: sender.Save += new EventSender.SaveEventHandler(Sender_Save);
Then create your event handler for the event. Returning true if Save was successful.
1: #region Save Event Handler
2:
3: /// <summary>
4: /// Save
5: /// </summary>
6: /// <param name="sender"></param>
7: /// <param name="e"></param>
8: /// <returns></returns>
9: private bool Sender_Save( object sender, System.EventArgs e )
10: {
11: bool _success = SaveData();
12:
13: return _success;
14: }
15:
16: #endregion
This way you can return values from the Event Handler back to the page.
Comments
Anonymous
November 28, 2008
What's wrong with inheriting from EventArgs and adding a bool property to keep your value. Just like the CancelEventArgs does.Anonymous
December 01, 2008
Also, for thread safety I recommend the following minor tweak: Change: if( Save != null ) _success = Save(this, e); To: SaveEventHandler handler = Save; if( handler != null ) _success = handle(this, e);Anonymous
October 13, 2010
Quote: "the value returned by the last handler executed will be the one returned to the event raiser." So your example does not work as expected. If I have a list of listeners and one of them wants, for example, cancel the ongoing/started operation by returning a specific value then this information would be lost if it is by luck not the last listener in the list. I would assume, that all return values should somehow be relevant. My 2 cents.