Create Event Handlers in Code in Silverlight for Windows Embedded (Compact 7)
3/12/2014
In Microsoft Silverlight for Windows Embedded, to handle events, you can attach C++ delegates to UI objects by using Add*EventHandler methods. Silverlight for Windows Embedded defines a C++ template class, IXRDelegate<ArgType, [SenderType]>, which represents a delegate that resembles a pointer to an event handler. Then, when a UI action raises that event, Silverlight for Windows Embedded calls IXRDelegate<ArgType, [SenderType]>::Invoke on the event delegate to invoke your event handler.
The way that you use events and delegates in Silverlight for Windows Embedded is different from Microsoft Silverlight for the desktop browser. In Silverlight for the desktop browser, you attach event handlers in XAML attributes or by using the common language runtime (CLR) event model in C#.
Create an Event Handler
To create an event handler in Silverlight for Windows Embedded, you first define a class that contains all the event handlers for your application; you then define event handlers for the events that you want to handle. An event handler in Silverlight for Windows Embedded must have a signature that matches the following signature.
HRESULT EventHandler(IXRDependencyObject* pSender, XREventArgs* pArgs);
In the signature, pSender must be of type IXRDependencyObject, and pArgs must be either XREventArgs or a type that is derived from XREventArgs.
In your event handler implementation, you can use QueryInterface to get a specific interface pointer to the IXRDependencyObject object sender (pSender), in order to call a method on the object that raised the event.
After you implement an event handler, you can create a delegate, and then attach the delegate to an event of a UI object.
The following example code shows an event handler in Silverlight for Windows Embedded.
Important
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 "XamlRuntime.h"
HRESULT OnMouseEnter(IXRDependencyObject* pSender, XRMouseEventArgs* pArgs)
{
IXRUIElementPtr pUIElement;
HRESULT hr;
bool Captured = false;
if((NULL == pSender) || (NULL == pArgs))
{
hr = E_INVALIDARG;
}
else
{
// Get XRMouseEventArgs.Position from the event data and
// add code for additional coordinate position processing
XRPoint Position = pArgs->Position;
// Get the object sender and call IXRUIElement::CaptureMouse
pSender->QueryInterface(IID_IXRUIElement, (void**)&pUIElement);
pUIElement->CaptureMouse(&Captured);
hr = S_OK;
}
return hr;
}
Retrieve Event Data
An event handler must accept an XREventArgs-derived structure that contains event data. Silverlight for Windows Embedded 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 XREventArgs-derived structure type that you provide in the event handler’s pArgs parameter must be the same structure type as the ArgType that you used in the pDelegate parameter of the Add*EventHandler method. For more information, see Add an Event Handler to Parsed XAML Elements later in this topic.
Modify Other UI Elements in Event Handling Code
An event handler takes two input parameters: the object sender and an event data structure. To access or modify an object in the visual tree other than the object sender, you need a pointer to the visual host.
To access the visual host in event-handling code, create a SetHost custom method in your event class that sets the pointer for the visual host to a variable in the event class. You can then 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 example shows an implementation of SetHost.
Important
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 "XamlRuntime.h"
class EventHandler
{
public:
IXRVisualHostPtr g_pHost;
HRESULT SetHost(IXRVisualHost* pHost);
{
HRESULT hr = S_OK;
ASSERT(! g_pHost);
if(NULL == pHost);
{
hr = S_FALSE;
return hr;
}
g_pHost = pHost;
return hr;
}
};
Add an Event Handler to Parsed XAML Elements
In Silverlight for Windows Embedded, you cannot add names of C# event handlers to XAML elements by using event handler syntax for an attribute of the 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 Visual Hosts and Visual Trees in Silverlight for Windows Embedded. For a list of the Add*EventHandler methods that are available in each object, see the reference documentation for that object.
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 a MouseEnter event for a button in C++, after the source XAML is parsed into a visual tree.
Important
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(IXRVisualHost* pVisualHost, CustomObject* pObject)
{
IXRButtonPtr pButton;
IXRFrameworkElementPtr pRootElement;
pVisualHost->GetRootElement(&pRootElement);
pRootElement->FindName(L"Button1", &pButton);
if (pButton)
{
pButton->AddMouseEnterEventHandler(CreateDelegate(pObject, &CustomObject::OnMouseEnter));
}
}