Are you using the MVVM pattern? Are you binding
ICommands to your button-based controls and handling the events in your view model? Have you seen the
RelayCommand? It's pretty cool, and I like that it lets you enable/disable your buttons by implementing a
CanExecutepredicate. Although I'm not trying to discourage you from using the
ICommandapproach to loose-coupling, you may however want to use (or maybe just learn about) another option.
This article is my first contribution to the community. I've created what I think is a nifty class and I'd like to share it with everyone. Perhaps someone will find it useful.
EventBrokerclass I'm going to talk about makes use of attached properties. If you're not familiar with these or just need a refresher, you can read about them on MSDN here.
Using the Code
First, we will see how to use the
EventBroker. It's really simple. Afterwards, for those who stick around, I will show what the code looks like.
So let's get started...
- Create a new WPF or Silverlight application and include EventBroker.cs in the project.
- If you chose WPF, open your MainWindow.xaml file. If you chose Silverlight, open your MainPage.xaml file.
- At the top of the XAML file, add a reference to the
- Edit the XAML to include a rectangle. We are going to handle the rectangle's
- To the rectangle, add the
MouseLeftButtonDownattached property. The value can be whatever
stringyou want (more on that later).
- Find a class that you would like to receive event notifications. I will choose the
MainWindowclass for this example. (Of course, putting the
EventBrokerhandler in the view's code-behind doesn't buy you anything since you could always do that. The beauty of the
EventBrokeris that you can handle the events in any arbitrary code!)
- Include the
EventBroker's namespace at the top of the file.
- In the constructor for the
MainWindowclass (or other appropriate location), attach to the one-and-only event published by the
- To handle the event, we must provide an event handler whose signature matches the
void EventManager_EventHandler(object sender, EventArgs e,
EventBroker.EventType eventType, string eventKey)
MessageBox.Show("eventKey = " + eventKey);
And that's it! Pretty simple, right! As this application runs, whenever you click inside the red rectangle, the above event handler will execute. Notice the arguments. The
eventType will indicate the type of event (in this case
eventKey argument will be the
stringyou assigned to the attached property in XAML. (in this case "Click!"). You can use either (or both) of these values for filtering. Unless you are using the
EventBrokerfor something like event logging, you would likely want to qualify the
eventKey before you react, as there may be many other controls that fire the same
MouseLeftButtonDownevent and you will probably want to react to each one differently.
So that brings up a point I want to make... When you attach to the
EventHandlerin the above fashion, you are essentially subscribing to a broadcast channel. All events processed by the
EventBrokerare broadcasted to all clients that have attached.
EventBrokeralso provides an API that allows clients to "
Register" for events. This puts the burden on the
EventBrokerto route events to the appropriate handlers. To register for an event, the code looks like this...
And when you're done listening to the event, you can "
Unregister" (make sure each parameter is the same as those used to register):
So, broadcasting or routing... You can choose the implementation that best fits your needs. The following list shows the events that are supported as of this writing.
Under the Hood
staticclass that implements a number of attached properties -- one for each event actually. The plumbing for these looks pretty typical. Here is the implementation for the
MouseLeftButtonDownattached property. We also must provide CLR
set()methods so we can use these properties in XAML.
public static readonly DependencyProperty MouseLeftButtonDownProperty =
new PropertyMetadata(String.Empty, OnMouseLeftButtonDownChanged)
public static string GetMouseLeftButtonDown(DependencyObject obj)
public static void SetMouseLeftButtonDown(DependencyObject obj, string value)
For each attached property definition, we provide a callback to give us a chance to hook up to the framework element's actual event interface. That code looks like this...
private static void OnMouseLeftButtonDownChanged(DependencyObject obj,
FrameworkElement target = obj as FrameworkElement;
if (target == null) return;
string newValue = e.NewValue as string;
string oldValue = e.OldValue as string;
if (!String.IsNullOrEmpty(newValue) && String.IsNullOrEmpty(oldValue))
target.Unloaded += new RoutedEventHandler(Proxy_UnLoaded);
else if (String.IsNullOrEmpty(newValue) && !String.IsNullOrEmpty(oldValue))
target.Unloaded -= new RoutedEventHandler(Proxy_UnLoaded);
First we coerce the
DependencyObject obj into a
FrameworkElement, which is the lowest common denominator control class that supports the mouse events. If the attached property is being set, then we attach to the control's
MouseLeftButtonDownevent. If the attached property is being cleared, then we detach from the control's
MouseLeftButtonDownevent. We also take this opportunity to attach/detach to/from the control's Unloaded event. This is monitored so we can detach our handlers from the control when the control gets unloaded. If we didn't do this, then the control would not get garbage collected. Yikes!
As you can see from the code above, whenever a
MouseLeftButtonDownevent occurs, the
Proxy_MouseLeftButtonDownhandler will execute. Each event type has its own
Proxy_XXXhandler. Here is an example of one...
private static void Proxy_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
string eventKey = GetMouseLeftButtonDown(sender as DependencyObject);
Fire_EventHandler(sender, e, EventType.MouseLeftButtonDown, eventKey);
Proxy_XXXhandler then calls a common method named
Fire_EventHandler, passing the
private static void Fire_EventHandler
(object sender, EventArgs e, EventType eventType, string eventKey)
if (EventHandler != null)
EventHandler(sender, e, eventType, eventKey);
List<eventcontract /> contracts = _Contracts.Where(c => (c.EventType == eventType) &&
(c.EventKey == eventKey)).ToList();
foreach (EventContract contract in contracts)
if (contract.EventHandler != null)
contract.EventHandler(sender, e, eventType, eventKey);
Fire_EventHandlermethod is responsible for broadcasting the event data to all clients/listeners, and to route the event data only to those interested (registered) parties. Internally, the
EventBrokermaintains a list of contracts that map the registered client handlers to event types and event keys (those
strings set in XAML).
Note: At the time of this writing, the
SelectionChangedevent only works with
ComboBoxcontrols, which are common to both WPF and Silverlight, and not
Well, I think that covers just about everything. I hope you find the
EventBrokeruseful. And if not, maybe you found an educational nugget in the article somewhere. Too-da-loo for now and happy coding!
- June 6, 2010 Created the article - DAB
- June 8, 2010 Updated source code to handle