Events Overview

This section describes the concept of events, events terminology, describes what routed events are and how are they routed through a tree of elements, summarizes how you handle events, and introduces how to create your own custom events.

Delegate Events

A delegate event exposes a simple delegate that will be called when the event is raised. Each event is referenced by a delegate stored in the class instance.

Connect Event Handlers

Each event must have a function named as the event returning a DelegateEvent_ wrapper, which implements operator += to add a new handler to the event and operator -= to remove a handler.

classDownloadControl:publicControl{public:DelegateEvent_<DownloadCompletedEventHandler>DownloadCompleted(){returnDelegateEvent_<DownloadCompletedEventHandler>(_downloadCompleted);}//...};// another class registers against the event...DownloadHandler::DownloadHandler(DownloadControl*control){control->DownloadCompleted()+=MakeDelegate(this,&DownloadHandler::OnDownloadCompleted);}voidDownloadHandler::OnDownloadCompleted(BaseComponent*sender,constDownloadCompletedEventArgs&args){//...}

Raise the Event

Each event should have an associated virtual function with the name of the event prefixed by On that will raise the event and will allow inheritors to handle the event and cancel it. For example, in the previous example that function would be OnDownloadCompleted().

Inside a Template

When the UI element forms part of a template it should override CloneOverride() method to clone all its members, so element is correctly replicated when template gets applied. Events should be cloned too, so generated template elements can notify to the code-behind object.

UIElement Events

UIElement provides static storage for delegate events, so you can define many events in a class without growing instance size.

Connect Event Handlers

In this case events will be exposed through a function that will return an Event_ wrapper defined by UIElement, which also implements operator += to add a new handler to the event and operator -= to remove a handler.

NS_DECLARE_SYMBOL(DownloadCompleted)classDownloadControl:publicControl{public:UIElement::Event_<DownloadCompletedEventHandler>DownloadCompleted(){returnUIElement::Event_<DownloadCompletedEventHandler>(this,NSS(DownloadCompleted));}// Needed by NsEventEventHandler&DownloadControl::GetDownloadCompletedEvent(){returnGetEventHandler(NSS(DownloadCompleted));}//...};// another component registers against the event...DownloadHandler::DownloadHandler(DownloadControl*control){control->DownloadCompleted()+=MakeDelegate(this,&DownloadHandler::OnDownloadCompleted);}voidDownloadHandler::OnDownloadCompleted(BaseComponent*sender,constDownloadCompletedEventArgs&args){//...}

Register Event

The same as with delegate events, if you want the event to be recognized by the XAML parser, you must register it inside class reflection.

Event Name Conventions

There are established naming conventions regarding routed events too. The routed event itself will have a basic name, DownloadCompleted. That name must be unique within each registering type. When you create the identifier field, name this field by the name of the event as you registered it, plus the suffix Event. This field is your identifier for the routed event, and it will be used later as an input for the AddHandler and RemoveHandler calls made when registering event handlers. That's why previous example used DownloadCompletedEvent as event identifier.

Register Event

In order for your event to support event routing, you must register that event into a table maintained by the type metadata, and give it a unique identifier. To register the event, you call the RegisterEvent() method within the body of your reflection implementation function.

Register Event Handlers

Each event needs to have a function named as the event and returning a RoutedEvent_ wrapper, defined by UIElement and implementing operator += to call AddHandler() and operator -= to call RemoveHandler(). That way users of the class can easily add handlers to events.

classDownloadControl:publicControl{public:UIElement::RoutedEvent_<DownloadCompletedEventHandler>DownloadCompleted(){returnUIElement::RoutedEvent_<DownloadCompletedEventHandler>(this,DownloadCompletedEvent);}//...};// another class registers against the event...DownloadHandler::DownloadHandler(DownloadControl*control){control->DownloadCompleted()+=MakeDelegate(this,&DownloadHandler::OnDownloadCompleted);}voidDownloadHandler::OnDownloadCompleted(BaseComponent*sender,constDownloadCompletedEventArgs&args){//...}

Raise the Event

Each event must have an associated virtual function with the name of the event prefixed by On that will raise the event and will allow inheritors to handle the event and cancel it. For the previous example the function would be OnDownloadCompleted().

Code-Behind Events

Code behind is the code that is joined with markup-defined objects. The XAML language includes the keyword x:Class that make it possible to associate code files with markup files, from the markup file side.

Code-behind class

The class specified in x:Class must derive from the type that backs the root element.

<UserControlx:Class="Samples.DownloadHandler">
...
</UserControl>

classDownloadHandler:publicUserControl{//...};

Event handlers

The event handlers you write in the code behind must be non-static instance methods. These methods must be defined by the class within the namespace identified by x:Class. You cannot qualify the name of an event handler to instruct the XAML parser to look for an event handler in a different class scope.

The handler must match the delegate for the appropriate event in the backing type system.

Event connection

In order to link events with code behind class, XAML parser will call during parsing process the function ConnectEvent() defined by the code behind instance for each event found in the XAML. This function provides the name of the event being linked, the name of the event handler that should be attached, and the source object where event will occur.