Data binding in Silverlight for Windows Embedded (SWE)

1.8k views Asked by At

Can someone please point me to a working example of how I'm supposed to do data binding in Silverlight for Windows Embedded (SWE). I have seen a showcase of it, so it appears to be possible. And I've read here that I need to implement IXRPropertyBag to make it work, but have yet to find (working) instructions on how to do it.

2

There are 2 answers

0
Kristoffer On BEST ANSWER

I managed to get data binding working between the IsChecked property of two ToggleButton elements, based on the insanely bad example found in the help files that came with the WCE7 CTP. I would have expected to set the data context and data bindings in XAML, but the documentation told me to code it.

First you have to create a class that implements IXRPropertyBag. Then you have to set the data context and data binding to an instance of this property bag from code.

I'm sorry for the lack of a naming convention in the code, but it is still far better than the example that was provided by Microsoft. It is also not as generic as it could be, but I'll leave that refactoring up to you.

MyPropertyBag.h:

#pragma once
#include "windows.h"
#include "XamlRuntime.h"
#include "XRCustomEvent.h"
#include "XRPtr.h"

class __declspec(uuid("3C6FFC6F-17A8-4976-B034-B4FE3BFF530A"))
MyPropertyBag : public IXRPropertyBag
{
private:
    LONG m_cRef;
    IXRCustomEvent<XRPropertyChangedCustomEventArgs, IXRPropertyBag> *pRadioEvent;
    XRThreeState RadioState;

public:
    MyPropertyBag(void);

    HRESULT STDMETHODCALLTYPE GetValue(__in const WCHAR* pstrPropertyName, __out XRValue *pValue);
    HRESULT STDMETHODCALLTYPE SetValue(__in const WCHAR* pstrPropertyName, __in XRValue *pValue);
    HRESULT STDMETHODCALLTYPE GetPropertyChangedEvent(__out IXRCustomEvent<XRPropertyChangedCustomEventArgs, IXRPropertyBag>** ppEvent);

    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID * ppvObj);
    ULONG STDMETHODCALLTYPE AddRef();
    ULONG STDMETHODCALLTYPE Release();
};

MyPropertyBag.cpp:

#include "StdAfx.h"
#include "MyPropertyBag.h"

extern "C" const GUID __declspec(selectany) IID_MyPropertyBag = __uuidof(IXRPropertyBag);

MyPropertyBag::MyPropertyBag(void)
{
    RadioState = XRThreeState_Unchecked;
    pRadioEvent = CreateCustomEvent<XRPropertyChangedCustomEventArgs, IXRPropertyBag>();
}

// IXRPropertyBag implementation:

HRESULT MyPropertyBag::GetValue(__in const WCHAR* pstrPropertyName, __out XRValue *pValue)
{
    HRESULT hr = E_FAIL;
    if (0 == wcscmp(pstrPropertyName, L"RadioState"))
    {
        pValue->vType = VTYPE_INT;
        pValue->IntVal = (int)RadioState;
        hr = S_OK;
    }

    return hr;
}

HRESULT MyPropertyBag::SetValue(__in const WCHAR* pstrPropertyName, __in XRValue *pValue)
{
    HRESULT hr = E_FAIL;

    if (0 == wcscmp(pstrPropertyName, L"RadioState"))
    {
        RadioState = (XRThreeState)pValue->IntVal;
        XRPropertyChangedCustomEventArgs eventArgs;
        eventArgs.PropertyName = pstrPropertyName;
        pRadioEvent->Raise(this, &eventArgs);
        hr = S_OK;
    }

    return hr;
}

HRESULT MyPropertyBag::GetPropertyChangedEvent(IXRCustomEvent<XRPropertyChangedCustomEventArgs, IXRPropertyBag>** ppEvent)
{
    *ppEvent = pRadioEvent;
    return S_OK;
}
// end of IXRPropertyBag implementation.

// IUnknown implementation:

HRESULT MyPropertyBag::QueryInterface(REFIID riid, LPVOID * ppvObj)
{
    if (!ppvObj)
        return E_INVALIDARG;

    *ppvObj = NULL;
    if (riid == IID_IUnknown || riid == IID_MyPropertyBag)
    {
        *ppvObj = (LPVOID)this;
        AddRef();
        return NOERROR;
    }

    return E_NOINTERFACE;
}

ULONG MyPropertyBag::AddRef()
{
    InterlockedIncrement(&m_cRef);
    return m_cRef;
}

ULONG MyPropertyBag::Release()
{
    ULONG ulRefCount = InterlockedDecrement(&m_cRef);
    if (0 == m_cRef)
    {
        delete this;
    }
    return ulRefCount;
}
// end of IUnknown implementation.

Create the shared property bag and call BindDataToControl for both toggle buttons before calling StartDialog on the visual host:

// Data bindings
XRPtr<MyPropertyBag> viewModel(new MyPropertyBag());
BindDataToControl(pTb1, viewModel);
BindDataToControl(pTb2, viewModel);

// save the exit code for WinMain
hr = m_pVisualHost->StartDialog(&uiExitCode);
SetWinMainResultCode(uiExitCode);  

This is what BindDataToControl would look like, to set the DataContext and the binding:

inline void App::BindDataToControl(IXRFrameworkElement* pElement, IXRPropertyBag* pPropertyBag)
{
    // Set the binding value and source property
    XRBinding binding;
    binding.Mode = XRBindingMode_TwoWay;
    binding.Path = L"RadioState";
    pElement->SetBinding(L"IsChecked", &binding); 

    // Convert the data source object to an XRValue
    XRValue dataContext;
    dataContext.vType = VTYPE_PROPERTYBAG;
    dataContext.pPropertyBagVal = pPropertyBag;

    // Set the data source object as the data context for the option button
    pElement->SetDataContext(&dataContext);
}
0
JohnDr On

You could also use TBoundProperty - see this Hands on labs for a simple example of binding the width of an ellipse to a slider.

MSDN Virtual Lab: Data Binding in Silverlight for Windows Embedded

https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032474142&EventCategory=3&culture=en-US&CountryCode=US