如何在代码中创建XAML自定义控件? [英] How to create a XAML custom control in code?
问题描述
我正在尝试使用C ++ / WinRT在代码中实现自定义XAML控件。但是,我尝试的实现未能编译。作为概念证明,我使用了以下代码:
I am trying to implement a custom XAML control in code, using C++/WinRT. My attempted implementation, however, failed to compile. As a prove of concept I was using this code:
#pragma once
#include <winrt/Windows.UI.Xaml.Controls.h>
namespace MyApp
{
struct MyControl : winrt::implements<MyControl, winrt::Windows::UI::Xaml::Controls::Control>
{
};
}
这导致以下编译器错误:
This resulted in the following compiler error:
1>MyControl.cpp
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(6416): error C2079: 'winrt::impl::producer<D,winrt::Windows::UI::Xaml::Controls::Control,void>::vtable' uses undefined struct 'winrt::impl::produce<D,I>'
1> with
1> [
1> D=MyApp::MyControl
1> ]
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(7163): note: see reference to class template instantiation 'winrt::impl::producer<D,winrt::Windows::UI::Xaml::Controls::Control,void>' being compiled
1> with
1> [
1> D=MyApp::MyControl
1> ]
1>c:\xxx\mycontrol.h(8): note: see reference to class template instantiation 'winrt::implements<MyApp::MyControl,winrt::Windows::UI::Xaml::Controls::Control>' being compiled
我无法了解编译器错误。显然,您不能以与实现Windows Runtime使用的其他类型相同的方式来实现XAML控件。
I am unable to understand the compiler error. Apparently, you cannot implement a XAML control the same way you would implement other types for use by the Windows Runtime.
在代码中实现XAML自定义控件需要什么?
What is required to implement a XAML custom control in code?
推荐答案
WinRT中的继承或子类化与C ++继承有细微差别。因为这些是COM接口,所以当您继承WinRT运行时类时,您真正要做的是 COM聚合,并结合实现基本类型的可覆盖的接口。由于COM聚合方面的原因,这比标准的C ++继承,所有委派的/非委托的,特殊的构造等要复杂得多。这将是WRL的一大难题,但是C ++ / CX在将其抽象化的引擎盖。幸运的是,C ++ / WinRT可以在不借助无形魔术的情况下为您提供两种抽象类型。
"Inheriting" or "subclassing" in WinRT is subtly different from C++ inheritance. Because these are COM interfaces, when you subclass a WinRT runtimeclass, what you're really doing is COM Aggregation, combined with implementing the base type's overridable interfaces. Due to the COM aggregation aspect, this is considerably more fussy than standard C++ inheritance, what with all the delegating/nondelegating, special construction, etc. This would be a major pain in WRL, but C++/CX did a bunch of compiler magic under the hood to abstract this away. Fortunately, C++/WinRT helps you out here with providing two types of abstractions, without resorting to invisible magic.
如果您正在编写的类型不需要在外部可见(例如,一个应用程序,而不是一个运行时组件),C ++ / WinRT为此提供了方便的助手:
If you are authoring a type that doesn't need to be externally visible (e.g. an app, as opposed to a runtime component) C++/WinRT provides convenient helpers for this:
#pragma once
#include <winrt/Windows.UI.Xaml.Controls.h>
namespace MyApp
{
struct MyControl : winrt::Windows::UI::Xaml::Controls::ControlT<MyControl>
{
void OnTapped(winrt::Windows::UI::Xaml::Input::TappedRoutedEventArgs const&);
};
}
此基本类型 ControlT
会正确构造聚合的基础 Control
实例并将基础方法委托给它,同时还实现可重写接口。这些可重写方法都提供了一个占位符实现,默认情况下将调用该基本方法,但是您可以自己重写它们并获得自定义行为。
This base type ControlT
will correctly construct the aggregated base Control
instance and delegate base methods to it, while also implementing the "overridable" interfaces. These overridable methods are all given a placeholder implementation that defaults to calling the base method, but you can override them yourself and get your custom behavior.
如果另一方面,您需要通过IDL编写一个投影类型:
If, on the other hand, you need to author a type that's projected, via IDL:
namespace MyApp
{
[default_interface]
runtimeclass MyControl : Windows.UI.Xaml.Controls.Control
{
MyControl();
};
}
这将产生与内置类似的支架上面的ControlT
案例,也可以投影您的类型。实际上,如果检查生成的这种类型的文件(在本例中为MyControl.gh),则会看到 MyControlT
,该文件都已连接上。
That will generate similar scaffolding as the built-in ControlT
case above, but also projects your type. In fact, if you examine the generated file for this type (in this example, MyControl.g.h), you'd see a MyControlT
where that gets all hooked up.
(注意:仅当您有一个空的,可构造的,密封的运行时类时,才需要 [default_interface]
属性。添加成员后,midl将自动合成默认界面,而无需任何其他诱因。
(Note: the [default_interface]
attribute is only needed if you have an empty, constructible, sealed runtimeclass. Once you add members, midl will figure synthesize the default interface without any other coaxing.
这篇关于如何在代码中创建XAML自定义控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!