在 C++ WinUI3 应用程序中 进行数据绑定 时(感谢 SimonMourier 的 demo,我学到了一些知识),我也在查看 {CustomResource} 数据绑定方法。
我创建 WinUI 打包项目
在 MainWindow.xaml 中我放置:
<TextBlock Text="{CustomResource Test1}"></TextBlock>
我将创建
winrt::Microsoft::UI::Xaml::Resources::CustomXamlResourceLoader
的后代:
class CLX : public winrt::Microsoft::UI::Xaml::Resources::CustomXamlResourceLoader
{
winrt::Windows::Foundation::IInspectable GetResource(const winrt::param::hstring& resourceId, const winrt::param::hstring& objectType, const winrt::param::hstring& propertyName, const winrt::param::hstring& propertyType) const
{
return winrt::box_value(L"hello");
}
};
在实现中我会添加一个变量:
CLX clx;
应用程序运行时,我收到预期的异常:
Exception thrown at 0x00007FFE9E97567C (KernelBase.dll) in app1.exe: WinRT originate error - 0x80004005 : 'No custom resource loader set.'.
Microsoft.UI.Xaml.dll!00007FFE3F265DD3: 80004005 - Unspecified error
Exception thrown at 0x00007FFE9E97567C (KernelBase.dll) in app1.exe: WinRT originate error - 0x802B000A : 'No custom resource loader set. [Line: 12 Position: 22]'.
现在,在 OnLaunched() 中:
winrt::Microsoft::UI::Xaml::Resources::CustomXamlResourceLoader::Current(clx);
这会导致不同的异常:
Exception thrown at 0x00007FFE9E97567C (KernelBase.dll) in app1.exe: WinRT originate error - 0x802B000A : 'Markup extension could not provide value. [Line: 12 Position: 22]'.
所以它看到了该处理程序,因为它似乎尝试调用它,但那里的断点没有命中也不能放置。该函数似乎从未被编译过。这不是很奇怪吗,这不是运行时功能吗?
我的 GetResource() 实现正确吗? 我不知道从现在开始该怎么办。
虽然这在编译时有效:
class CLX : public winrt::Microsoft::UI::Xaml::Resources::CustomXamlResourceLoader
{
winrt::Windows::Foundation::IInspectable GetResource(const winrt::param::hstring& resourceId, const winrt::param::hstring& objectType, const winrt::param::hstring& propertyName, const winrt::param::hstring& propertyType) const
{
return winrt::box_value(L"hello");
}
};
GetResource
方法不会被调用,因为它“只是”一个 C++ 方法,而内置 CustomXamlResourceLoader
将此方法实现为 ICustomXamlResourceLoaderOverrides
COM 接口的方法。
C++/WinRT 为所有 WinRT 类型提供了一个名为
[Type]T
的实用程序类来包装所有这些 COM 管道,因此如果您像这样声明它,它将起作用:
struct CLX : winrt::Microsoft::UI::Xaml::Resources::CustomXamlResourceLoaderT<CLX>
{
IInspectable GetResource(const hstring& resourceId, const hstring& objectType, const hstring& propertyName, const hstring& propertyType) const
{
return winrt::box_value(L"hello");
}
};
并像这样实例化:
void App::OnLaunched([[maybe_unused]] LaunchActivatedEventArgs const& e)
{
auto clx = make<CLX>();
winrt::Microsoft::UI::Xaml::Resources::CustomXamlResourceLoader::Current(clx);
...
}