Event Bindings outside of WPF
The code for this blog post can be downloaded from EventBindingTests.zip.
The solution file
EventBindingTests.sln is located under EventBindingTests\TESTS\EventBindingTests
Here I continue a series of blog posts about implementing WPF concepts outside of WPF.
In fact here, I am going to describe a concept/pattern that does not exist in WPF but, based on
my experience will be useful in WPF-esq universe – the Event Binding.
WPF creates various hierarchies of objects – there is a logical tree, there is a visual tree. When programming
MVVM there is also unspoken, but widely used hierarchy of the view models – e.g. a top level View Model might
contain some member representing another View Model or it might contain a collection of the view models representiong e.g. rows in a table or entries in a
Many time there should be an action from a sub-View Model to the one of its ‘anscestors’ in the View Model
hierarchy. This might happen, e.g. when a visual action is invoked on the sub-View Model but should result in
a change on its ‘anscestor’ level. The simplest example would be a remove button on each of the items within a list view. If implemented view the View Model patters, the remove button will have access only to the sub-View Model corresponding to individual item. However, the remove action should happen on the collection that contains the items’ View Models, i.e. a level higher. The way to implement it would be to create a ‘remove action’ event that fires at the item View Model level. When item becomes part of the collection in the higher level View Model – it adds a handler to the event that actually removes the item. The higher level View Model needs to manage adding and removing handlers to the items as they are added or removed to or from the collection or as the collection of items is getting totally overriden by a different collection.
The purpose of the Event Binding is precisely to make it easier to
manage the event handlers added at the ‘anscestor’ level to the ‘descendant’ item events.
Demonstration of what one can do with Event Binding
The main program is in
Programs.cs file of
EventBindingTests project. It demonstrates
binding an event handler to a single object or to a collection of objects.
Single Object Event Binding
Here is the single object event binding code (do not try to read to much into it since it is explained step by step below:
PopulatedOrganization wonkaFactory = new PopulatedOrganization(); Organization chocolateDepartment = new Organization(); #region SINGLE OBJECT EVENT BINDING // create the event binding for single object EventBinding<Organization, string> eventBinding = new EventBinding<Organization, string>(); // specify the source object and the path to the source binding property that contains the event // we want to bind to eventBinding.SourceObj = wonkaFactory; eventBinding.SourcePathLinks = StringCodePathResolver.ResolveStringPath("TheMostImportantDepartment").ToList(); // do the binding itself eventBinding.Bind(); // specify the event name (it can be done either before or after bind() // method is called eventBinding.EventName = "SomethingHappenedInOrgEvent"; // add the event hanlder whose signature is similar to that of // SomethingHappenedInOrgEvent event to the binding eventBinding.TheEvent += eventBinding_SomethingHappenedInTheDepartment; // nothing is printed to the console because wonkaFactory.TheMostImportantDepartment // is still not set to chocolateDepartment object chocolateDepartment.FireSomethingHappenedEvent("Augustus Gloop went to the chocolate creek. (Before the department added - should not show)" ); // set wonkaFactory.TheMostImportantDepartment wonkaFactory.TheMostImportantDepartment = chocolateDepartment; // this message is printed on the console chocolateDepartment.FireSomethingHappenedEvent("Augustus Gloop is out of the game (should show)"); // unbind the event eventBinding.Unbind(); #endregion SINGLE OBJECT EVENT BINDING
Here is the description of what is going on in the code.
has a property
TheMostImportantDepartment which is also of
Organization also has an event
This event is of the type
SomethingHappenedDelegate which is similar to
fires the event passing the
message to it.
We want to bind the
SomethingHappenedInOrgEvent on the
property of the organization to a handler at the main program level. For this purpose we use the Event Binding:
// create the event binding for single object EventBinding<Organization, string> eventBinding = new EventBinding<Organization, string>(); // specify the source object and the path to the source binding property that contains the event // we want to bind to eventBinding.SourceObj = wonkaFactory; eventBinding.SourcePathLinks = StringCodePathResolver.ResolveStringPath("TheMostImportantDepartment").ToList(); // do the binding itself eventBinding.Bind(); // specify the event name (it can be done either before or after bind() // method is called eventBinding.EventName = "SomethingHappenedInOrgEvent";
The above code does the binding. Note that the binding is already there even though the
TheMostImportantDepartment property has not been set yet.
Now we add the event handler to the Event Binding
and not to the original event:
// add the event handler whose signature is similar to that of // SomethingHappenedInOrgEvent event to the binding eventBinding.TheEvent += eventBinding_SomethingHappenedInTheDepartment;
This event handler will simply print the message argument from the event.
Now if we try to fire the event on the
chocolateDepartment object – nothing should
TheMostImportantDepartment property of the
object is still not set to the
// nothing is printed to the console because wonkaFactory.TheMostImportantDepartment // is still not set to chocolateDepartment object chocolateDepartment.FireSomethingHappenedEvent("Augustus Gloop went to the chocolate creek. (Before the department added - should not show)" )
Now we set the property and fire an event again and the corresponding message should be printed on the console:
// this message is printed on the console chocolateDepartment.FireSomethingHappenedEvent("Augustus Gloop is out of the game (should show)");
Note that the Event Binding takes full care of figuring out if
the property is null or not and making the event binding behave accordingly as long as the binding notification
is on (for simple properties – that means firing
event when the
TheMostImportantDepartment property changes. Similar notifications
are available for
Attached/Dependency properties – but the
SourcePathLinks will have to reflect the corresponding
Note also that the even though we considered a path containing only one path link – we can
use arbitraty path links of arbitrary length for Event Bindings
as long as each link provides binding notifications.
Collection Event Binding
Collection Event Binding provides even more dramatic refactoring.
Not only it takes case of collection being reset, but also if the collection implmements
INotifyCollectionChanged interface (i.e.
it adds or removes proper handlers when the items of the
collection are added or removed correspondingly.
An organization has
AllDepartments property of type
ObservableCollection<Organization>. We want to set the collection, add a couple of departments
to it use Event Binding to bind the
on the collection objects to our event handler. Here is the corresponding code:
#region COLLECTION EVENT BINDING // create the collection AllDepartments wonkaFactory.AllDepartments = new ObservableCollection(); // add chocolate department to it wonkaFactory.AllDepartments.Add(chocolateDepartment); // create collection event binding CollectionEventBinding<Organization, string> collectionEventBinding = new CollectionEventBinding<Organization, string>(); // set the objects that contain the event we want to bind to // to be "AllDepartments" collection property of "wonkaFactory" object collectionEventBinding.SourceObj = wonkaFactory; collectionEventBinding.SourcePathLinks = StringCodePathResolver.ResolveStringPath("AllDepartments").ToList(); // bind the event collectionEventBinding.Bind(); // set the event name (can be done before or after the binding) collectionEventBinding.EventName = "SomethingHappenedInOrgEvent"; // add event handler collectionEventBinding.TheEvent += collectionEventBinding_TheEvent; // create gumDepartment Organization gumDepartment = new Organization(); // fire an event (should not be handled since gumDepartment is not part of the collection yet) gumDepartment.FireSomethingHappenedEvent("We had great sales (Before the department is added - should not show)"); // Add gum department to the collection wonkaFactory.AllDepartments.Add(gumDepartment); // fire the event (should be handled, since now gumDepartment is part of the collection) gumDepartment.FireSomethingHappenedEvent("We had great sales (After the department is added - should show)"); // remove gum department from All Department collection // collectionEventBinding should be sufficiently smart to disconnect // the event of gumDepartment object from the handler wonkaFactory.AllDepartments.Remove(gumDepartment); // fire the event again - (the handler should not run, since gumDepartment has been removed from the collection) gumDepartment.FireSomethingHappenedEvent("We had great sales (After the department is Removed - should not show)"); #endregion COLLECTION EVENT BINDING
The binding code is sufficiently similar to the case of a single object so that we do go
over each step again in detail. I’d like to re-iterate, however, that the
will manage the event handlers on each of the members of the collection both in case the whole collection
is re-assigned (if all the path links to the collection have binding notifications)
or in case elements are added or removed to or from it (if the collection implements
The central class for both
NP.Paradigms.EventBindingBase<ObjectType, EventObjectType>. It provided the actual binding
from the actual object in the hierarchy to the Event Binding‘s property
TheObj. This class has two generic parameters:
ObjectType is the type of the object that we bind to – in case of a single event binding – it is the
same as the type of the object that contains the event (
EventObjectType), while in case of a collection
event binding it is a collection of objects of type
This class contains two important abstract methods
Reconnect() that control removing or setting the event handler
on the corresponding object(s). These methods are overriden in concrete implementation of
This class defines also the name of the method that will be attached to the bound object(s) events:
This method is also defined in the sub-classes.
The reflection based actual implementation of adding and removing the handlers to the object is located
SingleObjectEventBindingBase is derived from
EventBindingBase it overrides
Reconnect() methods to act on a single object.
A number of
EventBinding classes with various generic parameters specifying different possible
arguments to the event is derived from
CollectionEventBindingBase class is also derived from
EventBindingBase by overriding the same
Reconnect() and specifying some handling when items are added or removed
to or from the collection.
A number of
CollectionEventBinding classes with various generic parameters is also derived
In this blog post I describe a new concept of Event Binding which is not part
of WPF but should come handy for programming using WPF related concepts (whether it used in WPF or outside of WPF).