Handle Events in Silverlight for Windows Embedded (Windows Embedded CE 6.0)
1/6/2010
The way that you use events and delegates in Silverlight for Windows Embedded is different from Microsoft Silverlight 2 for Web applications. Silverlight for Windows Embedded uses C++ delegates and event handlers to handle events, and ignores event handlers defined in XAML. In contrast, Microsoft Silverlight 2 attaches C++ delegates to UI objects to handle events through Add*EventHandler methods.
Silverlight defines a special type, IXRDelegate<ArgType> which represents a delegate that functions like a method pointer. When you attach a delegate to an event in a UI object and that event is raised, Silverlight calls Invoke on the event's delegate.
Create an Event Handler
To create an event handler, you first define a class that contains all the event handlers for your application, and then define event handlers for the events you want to handle. An event handler has a signature as follows:
class TestEventHandler
{
public:
HRESULT OnKeyDown( IXRDependencyObject* pSender, XRKeyEventArgs* pArgs )
{
//event handler implementation
}
};
You attach your event handler to an object by using the corresponding Add*EventHandler method on that object.
The following example shows how to use QueryInterface to get an interface pointer to the object sender in order to call a method on the object sender:
HRESULT OnMouseEnter(IXRDependencyObject* pSender, XRMouseEventArgs* pArgs)
{
IXRUIElement* pUIElement = NULL;
// declare boolean and initialize to false
bool Captured = false;
if (pArgs)
{
XRPoint Position = pArgs->Position;
}
pSender->QueryInterface(IID_IXRUIElement, &pUIElement);
if (pUIElement)
{
pUIElement->CaptureMouse(&Captured);
}
SAFE_RELEASE(pUIElement);
return S_OK;
}
Once you have implemented an event handler, you can create an instance of the event handler object, create a delegate for the handler instance, and then attach the delegate to an event of a UI object.
The following example code demonstrates how to do this for the custom OnMouseEnter example event handler:
TestEventHandler* HandlerObject;
pIButton->AddMouseEnterEventHandler(CreateDelegate(&HandlerObject, &TestEventHandler::OnMouseEnter));
For a list of Add*EventHandler methods available in each object, see the reference documentation for that object.
Specialized Event Data
An event handler must accept an XREventArgs derived structure that contains event data. Silverlight provides a variety of such event structures that contain data for specific types of events. As long as it reflects the appropriate event type, you can use any XREventArgs-derived structure in the method signature for your custom event handler. Then, you can extract data from the structure to determine information about the event. For example, XRMouseEventArgs provides a Position member that describes the x-coordinate and y-coordinate for the position on the screen where the mouse event occurred.
Note
The structure type that you provide in the second parameter of the event-handler function signature for the XREventArgs-derived structure must be the same as the structure type that you provide for the structure handled by the Add*EventHandler method that you use to attach the delegate to a UI object. This method is described later in this topic.
For a list of event structures, see Silverlight for Windows Embedded Structures.
Accessing the Visual Host
An event handler must accept the event sender and the event data structure as input parameters. To access or modify an object in the visual tree other than the event sender, you need a pointer to the visual host.
To access the visual host in event-handling code, you can create a SetHost custom method in your event class that sets the pointer to the visual host to a variable in the event class. Then, you can use that variable to access the visual host in any event handlers in your class.
Make sure that you call your SetHost method after you call IXRApplication::CreateHostFromXaml to set the IXRVisualHost pointer.
The following is an example implementation of SetHost:
class EventHandler
{
public:
IXRVisualHost* g_pHost;
HRESULT SetHost(IXRVisualHost* pHost);
{
HRESULT hr = S_OK;
ASSERT(! g_pHost);
if(NULL == pHost);
{
hr = S_FALSE;
return hr;
}
g_pHost = pHost;
g_pHost->AddRef();
return hr;
}
};
Adding an Event Handler to Parsed XAML Elements
In Silverlight for Windows Embedded, you cannot add event handlers to elements by using event handler syntax for the attributes of the XAML element. Instead, you must find each named element at run time and add event handlers to them by using the Add*EventHandler methods. To do this, you must retrieve an object pointer to each named element from the visual tree. For more information about the visual tree, see Populate On-Screen Content for a Silverlight for Windows Embedded Application.
You must know the x:Name values for each element that raises events to add an event handler to a parsed element. The x:Name values are defined in the source XAML file.
The following code example shows how to attach a delegate to this button's MouseEnter event in C++, after the source XAML is parsed into a visual tree.
Note
For readability, the following code example does not contain security checking or error handling. Do not use the following code in a production environment.
#include <windows.h>
#include <XamlRuntime.h>
#include <XRDelegate.h>
#include <XRPtr.h>
void AddEventHandler(IXRVisualHostPtr pVisualHost, TestEventHandler* pEventHandler)
{
IXRButtonPtr pButton;
IXRFrameworkElementPtr pRootElement;
pVisualHost->GetRootElement(&pRootElement);
pRootElement->FindName(L"Button1", &pButton);
pButton->AddMouseEnterEventHandler(CreateDelegate(pEventHandler, &TestEventHandler::OnMouseEnter));
pButton->Release();
}