如何在代码中创建XAML自定义控件? [英] How to create a XAML custom control in code?

查看:248
本文介绍了如何在代码中创建XAML自定义控件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆