Type-Safe Conversion of Generic Object Types in Silverlight for Windows Embedded (Compact 7)
3/12/2014
To work with UI objects in Microsoft Silverlight for Windows Embedded, you access them by their class type instead of by the generic object type that common methods return. For example, the Silverlight for Windows Embedded API provides methods such as IXRApplication::CreateObject, IXRFrameworkElement::FindName, and IXRFrameworkElement::GetParent. These methods typically return generic object types, such as IXRDependencyObject; however, to use the object that is returned, you must convert the object into the corresponding class, such as IXRButton. This topic describes how to do a type-safe conversion of a generic object type into the specific object type that you need.
To work with a specific type of object, you must use a derived interface type instead of IXRDependencyObject.
You can ensure that an object is a specific type in two ways:
Use a helper template overload method to retrieve a type-safe object. By using a helper template overload method, you can supply the specific object type to the method, and the method retrieves the object and converts it to the specified type so that you can use the object immediately. This approach simplifies your code and saves you time.
Note
Helper template overload methods are used for C++ programming in Silverlight for Windows Embedded and are not available in Microsoft Silverlight for the desktop browser.
Call IUnknown::QueryInterface on the object. Use this approach when the method does not support a helper template overload version.
Important
Using the QueryInterface approach can be error-prone; if you do not manually add it to your code in a consistent manner, type-safety issues can occur.
Helper Template Overload Method Example
The following example shows the signature of a template helper version of the IXRFrameworkElement::FindName method, which is defined in XamlRuntime.h.
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.
template<typename XRObj> HRESULT FindName(__in const WCHAR* pName,__out XRObj** ppFoundObject)
{
IXRDependencyObject* pTemp = NULL;
HRESULT hr = FindName(pName,&pTemp);
if(SUCCEEDED(hr) && pTemp)
{
hr = pTemp->QueryInterface(
__uuidof(XRObj),reinterpret_cast<void**>(ppFoundObject));
pTemp->Release();
}
return hr;
}
The following example shows how to use a helper template overload method to automatically convert a type from a generic interface to IXRButton.
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 hr;
IXRButton* pButton = NULL;
hr = pRoot->FindName(L"OKButton", &pButton);
if(SUCCEEDED(hr))
{
// Do something with your button
pButton->Release();
}
To make Silverlight for Windows Embedded application development easier and to ensure correct reference counting, you can use smart pointers that manage the reference count and ownership lifetime. When you use smart pointers, you do not have to call IUnknown::Release to release an interface to an object. The following example shows how to automatically convert a type by using smart pointers with helper methods.
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"
#include "XRPtr.h"
HRESULT hr;
IXRButtonPtr pButton;
hr = pRoot->FindName(L"OKButton", &pButton);
if(pButton)
{
// Use the button
}
QueryInterface Example
The following code example shows how to retrieve an object by using the QueryInterface method and then obtain the derived interface type. We recommend that you use this method only when a helper template overload method is unavailable.
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 hr;
IXRDependencyObject* pDO = NULL;
hr = pPanel->GetChildren(&pDO);
if(SUCCEEDED(hr))
{
IXRUIElementCollection* pCollection = NULL;
hr = pDO->QueryInterface(IID_IXRUIElementCollection,(void**)&pCollection);
if(SUCCEEDED(hr))
{
// Do something with your collection
pCollection->Release();
}
pDO->Release();
}