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
CanExecute predicate. Although I'm not trying to discourage you from using the
ICommand approach 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.
EventBroker class 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
MouseLeftButtonDown attached property. The value can be whatever
string you want (more on that later).
- Find a class that you would like to receive event notifications. I will choose the
MainWindow class for this example. (Of course, putting the
EventBroker handler in the view's code-behind doesn't buy you anything since you could always do that. The beauty of the
EventBroker is 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
MainWindow class (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
string you 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
EventBroker for 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
MouseLeftButtonDown event 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
EventHandler in the above fashion, you are essentially subscribing to a broadcast channel. All events processed by the
EventBroker are broadcasted to all clients that have attached.
EventBroker also provides an API that allows clients to "
Register" for events. This puts the burden on the
EventBroker to 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
EventBroker is a
static class 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
MouseLeftButtonDown attached 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
MouseLeftButtonDown event. If the attached property is being cleared, then we detach from the control's
MouseLeftButtonDown event. 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
MouseLeftButtonDown event occurs, the
Proxy_MouseLeftButtonDown handler will execute. Each event type has its own
Proxy_XXX handler. 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_XXX handler 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_EventHandler method 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
EventBroker maintains 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
SelectionChanged event only works with
ComboBox controls, which are common to both WPF and Silverlight, and not
Well, I think that covers just about everything. I hope you find the
EventBroker useful. 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
ToggleButton - DAB