How to Change Event Handlers at Run Time





0/5 (0 vote)
How to change event handlers at run time
One of the challenges when using event handlers at run time, in my opinion, is that we can't manage previously registered event handlers very easily. I mean we don't know who else is listening to the same event.
Suppose we have two combo boxes and a list box. We want to let the user select a category in the first combo box and select an object in the second combo box and see a list of related information of that object in the list box.
- User selects
Music
category fromcategory
combobox
. - User selects "
Abby Road
" from objectscombobox
. - A list of album information is shown to him.
Here's the source:
private void CategorySelected(object sender,EventArgs e)
{
if(
((Categroy)_categoryComboBox.SelectedItem).Type==
CategroyType.Music
)
{
_itemComboBox.DataSource=_application.GetMusicAlbums();
}
}
private void ItemSelected(object sender,EventArgs e)
{
if(_itemComboBox.SelectedItem is MusicAlbum)
{
_list.DataSource=
_application.
GetMusicAlbumAdditionalInfo
((MusicAlbum)_itemComboBox.SelectedItem);
}
}
Well it's working but it's not very nice. As you can see, we should write a lot of "if
" to handle different kinds of categories and objects.
OK we could change the event handler instead of using if
. Suppose that we have registered some event handlers in a dictionary
, then we can write:
_itemComboBox.SelectedItemChanged+=
_eventhandlersRegistry[selectedCategory.Type];
But we have a little problem: what if there's already a category selected? So we should first remove last SelectedItemChanged
event handler, then we have to write:
_itemComboBox.SelectedItemChanged-=
_lastSelectedItemChangedEventHandler
_itemComboBox.SelectedItemChanged+=
_eventhandlersRegistry[selectedCategory.Type];
_lastSelectedItemChangedEventHandler=
_eventhandlersRegistry[selectedCategory.Type];
To solve this kind of scenario, I recently use a solution that I'd like to share with you:
I use a nested EventHandler
delegate, therefore there's no need to change the event handler of actual event. Here's what I do: I have an event handler delegate declared as:
private EventHandler _nestedSelectedItemChangedEventHandler
Then I have this general event handler for the actual event:
_itemComboBox.SeletedItemChanged+=
GeneralItemChangedEventHandler;
When the category is changed, I place a new delegate in my nested event handler like this:
_nestedSelectedItemChangedEventHandler=
_registeredEventHandlers[_selectedCategory.Type];
and GeneralItemChangedEventHandler
will call nested event handler as follows:
private void GeneralItemChangedEventHandler (object sender,EventArgs e)
{
if(_nestedSelectedItemChangedEventHandler!=null)
_nestedSelectedItemChangedEventHandler(sender,e);
}
This approach can be used if you are implementing a strategy pattern so that you want to change the behavior by changing the state of your object and there's always a single event handler involved to handle an event.