WPF Delegate Events
In this tutorial we take the project from part 1 and add some basic functionality. The next step is to wire up events so that clicking on a tree view item will create a tab for the item clicked. This will require setting up custom event handlers for the tree view control and listening for those events in the parent window. We are going to ultimately set it up in a way that makes those custom events part of the valid XAML markup for our custom tree view control.
Be sure to get the ThoughtlabTutorial and look through its contents as you read the tutorial.
Custom Events
You should notice a new class file in the Classes directory in our project. Basically, we created our own RoutedEventArgs class for each type of object that is represented in the tree view. If you recall back in Project 1, we actually feed our objects directly to our tree view, and it’s templates decide how to display it. This means that when a user selects a tree view item, they have selected the object itself; pretty slick stuff. That in turn means that we can create RoutedEventArgs classes that contain the specific object in order to pass that object with the event.
public class ItemEventArgs : RoutedEventArgs
{
public ItemEventArgs(Item itm)
: base()
{
this.MyItem = itm;
}
public ItemEventArgs(RoutedEvent routedEvent, object source,
Item itm) : base(routedEvent, source)
{
this.MyItem = itm;
}
public Item MyItem { get; private set; }
}
As you can see there isn’t anything too unusual about these classes. You will also notice a separate namespace at the bottom of this file. In order for us to use the events as we plan to in our project, we need to create a delegate in the System.Windows.NameSpace.
namespace System.Windows
{
public delegate void RoutedEventHandler<TArgs>(object sender,
TArgs e) where TArgs : RoutedEventArgs;
}
Adding Events To Our User Control
Next you need to add events to the user control. Looking in the TreeViewControl.xaml.cs file you will see these events in a region named events. To add an event you need to create a RoutedEvent, and it’s companion RoutedEventHandler.
public static readonly RoutedEvent CustomerSelectedEvent =
EventManager.RegisterRoutedEvent
("CustomerSelected"
, RoutingStrategy.Direct
, typeof(RoutedEventHandler<CustomerEventArgs>)
, typeof(TreeViewControl)
);
public event RoutedEventHandler<CustomerEventArgs>
CustomerSelected
{
add { AddHandler(CustomerSelectedEvent, value); }
remove { RemoveHandler(CustomerSelectedEvent, value); }
}
Once you have gotten to this point you can now add an event in the XAML for the TreeViewControl. It even shows up in the intellisense for your control for you. Notice that this event is specifically using the CustomerEventArgs class. That means that the event you created will use that exact type of EventArgs object as its parameter. This makes it nice and easy to get the Customer object that the user selected from the tree view.
Raising Our Events
We are really close to finishing our interaction. At this point however, there is no code that actually raises the events we have created. You should notice that the XAML in TreeViewControl.xaml has changed slightly. We have now hooked up an event handler for SelectedItemChanged
<TreeView ItemsSource="{Binding ElementName=ctrlMyTreeView,
Path=MyCustomers}"
ItemTemplate="{StaticResource CustomerTemplate}"
SelectedItemChanged="TreeView_SelectedItemChanged">
When you have added that event in the XAML, you will need to create that event handler in code. The event we have looks like this:
private void TreeView_SelectedItemChanged(object sender,
RoutedPropertyChangedEventArgse)
{
Object selItem = (e.Source as TreeView).SelectedItem;
if (selItem is Customer)
{
raiseCustomerEvent(selItem as Customer);
}
if (selItem is Order)
{
raiseOrderEvent(selItem as Order);
}
if (selItem is Item)
{
raiseItemEvent(selItem as Item);
}
}
Obviously you now need to create those helper functions to raise each type of event. They are all very similar so we will only show one for the purpose of this tutorial:
private void raiseCustomerEvent(Customer c)
{
CustomerEventArgs args = new CustomerEventArgs(c);
args.RoutedEvent = TreeViewControl.CustomerSelectedEvent;
args.Source = this;
RaiseEvent(args);
}
Now the tree view will raise the event, and code in the WIndow1.xaml.cs can nowhandle it. All that remains is to use the handler event to create a new tab item and add it to the tab control (which you will also notice is new in this level of the tutorial).
private void TreeViewControl_CustomerSelected(object sender,
ThoughtlabTutorial.Classes.CustomEventArgs.CustomerEventArgs e)
{
TabItem ti = new TabItem();
ti.Header = "Customer";
ti.Content = new CustomerControl();
myTabControl.Items.Add(ti);
}
The project now has some stubbed out user controls like CustomerControl that obviously are needed for this code to work.
Wrapping Up
This gives you a good framework to create custom events, assign them in XAML and handle them effectively. The final part of this tutorial will talk about customizing our tab items, managing some interesting focus issues, and some other things that will make this general idea a lot more useful.












