Silverlight для Windows Embedded: как передать свойство зависимости источника изображения между xaml и code-behind

Я работаю над проектом Silverlight для Windows Embedded. Я определил пользовательский элемент управления, который состоит из элемента управления изображением. Я хочу указать другой источник изображения в xaml для другого экземпляра пользовательского элемента управления. Поэтому я определяю свойство зависимости "MyImage" в пользовательском элементе управления.

В коде Blend C#: public UserControl1() { InitializeComponent(); ItemImage.DataContext = this; }

    public ImageSource MyImage
    {
        get { return (ImageSource)GetValue(MyImageProperty); }
        set { SetValue(MyImageProperty, value); }
    }

    public static readonly DependencyProperty MyImageProperty =
        DependencyProperty.Register("MyImage", typeof(ImageSource), typeof(UserControl1), null);

В UserControl.xaml я связываю свойство Source элемента управления изображением с MyImage:

<Image x:Name="ItemImage" Margin="0,0,90,0" Source="{Binding MyImage}"/>

Поэтому, когда я использую пользовательский элемент управления, я могу сделать это в xaml:

<local:UserControl1 HorizontalAlignment="Left" Margin="94,117,0,0" Width="196" Height="85" VerticalAlignment="Top" MyImage="img1.png"/>
<local:UserControl1 HorizontalAlignment="Left" Margin="94,217,0,0" Width="196" Height="85" VerticalAlignment="Top" MyImage="img2.png"/>

Тестирование в Blend в порядке. Я вижу два изображения, показанные в двух экземплярах пользовательского элемента управления.

Затем, перейдя к программному обеспечению SWE C++, я переопределил и зарегистрировал свойство зависимости в UserControl1.cpp:

XRDependencyPropertyMetaData dpmImage = XRDependencyPropertyMetaData();
dpmImage.Size = sizeof(IXRImageSource);
dpmImage.pfnPropertyChangeNotification = ImagePropertyChanged;
dpmImage.pfnTypeConverter = ConvertNameTypeConverter;
dpmImage.pfnEnumerableCreation = NULL;

XRValue defImage;
defImage.vType = VTYPE_OBJECT;
defImage.pObjectVal = NULL;
dpmImage.DefaultValue = defImage;

hr = pApplication->RegisterDependencyProperty(L"MyImage", VTYPE_OBJECT, ControlID(), &dpmImage, &m_dpMyImageID);

void UserControl1::ImagePropertyChanged( __in IXRDependencyObject* pControl, __in XRValue* pOldValue, __in XRValue* pNewValue )
{......}
HRESULT UserControl1::ConvertNameTypeConverter( XRValue *pValIn, XRValue *pValOut )
{......}

Компиляция и выполнение прошло успешно, просто я не вижу изображений, отображаемых в двух элементах управления.

При отладке я вижу, что обратный вызов ConvertNameTypeConverter сначала вызывается. Я вижу, что имя файла изображения хранится в pValIn в виде строки, которая соответствует тому, что описывается в документации MSDN: Когда XAML для Windows Embedded вызывает эту функцию на этапе синтаксического анализа, pValIn всегда будет строкой.

Затем вызывается обратный вызов ImagePropertyChanged, и я вижу, что pNewValue содержит значения, которые я установил в pValOut в ConvertNameTypeConverter().

У меня вопрос, правильно ли я поступаю? Если я могу получить только строку для имени файла изображения, как я могу получить двоичный файл изображения из строки?

Есть ли способ прямой передачи двоичного изображения из кода xaml в код C++ и непосредственного отображения?

Спасибо!

2 ответа

Решение

Задача решена. Но я думаю, что мое решение выглядит как обходной путь. В обратном вызове я попытался использовать LoadImageFromResource для загрузки двоичного изображения из файла ресурсов:

void UserControl1::ImagePropertyChanged( __in IXRDependencyObject* pControl, __in XRValue* pOldValue, __in XRValue* pNewValue )
{
    IWICBitmap *pImage = NULL;
    IXRBitmapImagePtr pBitmap;
    GetXRApplicationInstance(&pApplication);
    pApplication->LoadImageFromResource(App::GetHInstance(), pNewValue->bstrStringVal, L"XAML_RESOURCE", &pImage);

    pApplication->CreateObject(&pBitmap);
    pBitmap->SetSource(pImage);
    pApplication->Release();

    UserControl1 *tempObj;
    pControl->QueryInterface(__uuidof(UserControl1), (void**)&tempObj);
    tempObj->m_pItemImage->SetSource((IXRImageSource*)pBitmap);
}

Однако второй аргумент pResourceName ожидает идентификатор ресурса, автоматически сгенерированный XRPack в файле.rc. Например:

103 XAML_RESOURCE DISCARDABLE "..\\..\\..\\..\\Expression\\Blend_3\\Projects\\WindowsEmbeddedSilverlightApplication1\\WindowsEmbeddedSilverlightApplication1\\img1.png"

Тогда pResourceName должно быть MAKEINTRESOURCE(103).

Поскольку идентификатор автоматически назначается XRPack, я не могу узнать имя изображения для сопоставления идентификатора динамически.

Поэтому я пишу Perl-скрипт для обработки файла.rc и преобразую приведенную выше строку в:

img1.png XAML_RESOURCE DISCARDABLE "..\\..\\..\\..\\Expression\\Blend_3\\Projects\\WindowsEmbeddedSilverlightApplication1\\WindowsEmbeddedSilverlightApplication1\\img1.png"

В VS я настраиваю скрипт для запуска после того, как XRPack сгенерирует файл.rc и перед началом компиляции. Вот как

LoadImageFromResource(App::GetHInstance(), pNewValue->bstrStringVal, L"XAML_RESOURCE", &pImage);

буду работать.

Вы можете определить идентификаторы, которые генерируются XRPack. Для этого определите в своем коде XAML:

<Image xrpack:Resource="Source:902(IDR_SETTINGS)" Margin="0" Source="Image.png"/>

Если вы используете Expression Blend, вам, вероятно, также придется определить пространство имен для "xrpack". Для этого определите в UserControl:

mc:Ignorable="d xrpack"
xmlns:xrpack="http://schemas.microsoft.com/windowsembedded/silverlight/packaging"

В коде C++ теперь вы можете использовать метод LoadImageFromResource:

LoadImageFromResource(App::GetHInstance(), MAKEINTRESOURCE(IDR_SETTINGS), L"XAML_RESOURCE", &pImage);
Другие вопросы по тегам