Uwp 如何在代码中创建XAML自定义控件?

Uwp 如何在代码中创建XAML自定义控件?,uwp,c++-winrt,Uwp,C++ Winrt,我试图用C++/WinRT在代码中实现一个自定义XAML控件。但是,我尝试的实现未能编译。作为概念证明,我使用了以下代码: #pragma一次 #包括 名称空间MyApp { struct MyControl:winrt::implements { }; } 这导致以下编译器错误: 1>MyControl.cpp 1> c:\program files(x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(6416):错

我试图用C++/WinRT在代码中实现一个自定义XAML控件。但是,我尝试的实现未能编译。作为概念证明,我使用了以下代码:

#pragma一次
#包括
名称空间MyApp
{
struct MyControl:winrt::implements
{
};
}
这导致以下编译器错误:

1>MyControl.cpp
1> c:\program files(x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(6416):错误C2079:“winrt::impl::producer::vtable”使用未定义的结构“winrt::impl::producer”
1> 与
1>        [
1> D=MyApp::MyControl
1>        ]
1> c:\program files(x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(7163):注意:请参阅正在编译的类模板实例化“winrt::impl::producer”
1> 与
1>        [
1> D=MyApp::MyControl
1>        ]
1> c:\xxx\mycontrol.h(8):注意:请参阅对正在编译的类模板实例化“winrt::implements”的引用
我无法理解编译器错误。显然,不能像实现Windows运行时使用的其他类型那样实现XAML控件

在代码中实现XAML自定义控件需要什么?

< P>“继承”或“子类”在WinRT中与C++继承有细微区别。因为这些是COM接口,所以当您对WinRT runtimeclass进行子类化时,您真正要做的是结合实现基类型的。由于COM聚合方面,这比标准的C++继承更为繁琐,这与所有委托/非委托、特殊构造等有关。这将是WRL中的一个主要问题,但是C++/CX在引擎盖下做了一组编译魔法来抽象这个。幸运的是,C++/WinRT在这里帮助您提供了两种类型的抽象,而无需借助无形的魔法

如果您正在创作不需要外部可见的类型(例如,应用程序,而不是运行时组件),C++/WinRT为您提供了方便的帮助:

#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
案例类似的脚手架,但也会投影您的类型。事实上,如果您检查生成的文件中的这种类型(在本例中为MyControl.g.h),您会看到一个
MyControlT
,它将所有的内容连接起来


(注意:
[默认\u界面]
属性仅当您有一个空的、可构造的、密封的运行时类时才需要。一旦您添加了成员,midl将在没有任何其他诱使的情况下合成默认接口。

可以使用C#?我不知道如何在C++@lindexi中实现它:我不想引入任何其他依赖项,所以不,不需要C#。
实现了
class模板的级别非常低,因为它只帮助您实现接口。
Control
不是一个接口,这就是它不起作用的原因。您必须列出所有需要实现的接口。问题是控件非常复杂,这就是通过proje提供创作支持的原因ct模板很有用。如果没有其他内容,您应该尝试使用
-component
选项来生成脚手架。@KennyKerr:我确实尝试过在.idl文件(
名称空间MyApp{runtimeclass MyControl:Windows.UI.Xaml.Controls.control{})中声明我的控件
。该工具也生成了实现文件,但这些文件包含意外的内容(本质上是
名称空间winrt::MyApp::implementation{struct MyControl{MyControl()=delete;};}
)。如果不支持从具体实现派生,我会预期生成工具会出现错误。Windows.UI.Xaml.Controls.h中也有
struct-ControlT
,但我不确定这到底是怎么回事。这很有用,一如既往。从
ControlT
模板派生对我来说很有用,尽管所有IntelliSense支持已消失。另一方面,使用IDL失败:
错误MIDL5053:[msg]空运行时类不能具有[composable]或[activatable]属性[context]:[RuntimeClass'MyApp.MyControl']
。如果省略默认的c'tor,生成的代码只包含一个结构,没有任何基类。我使用的是10.0.17125.0 SDK和VSIX 1.0.180505.2。从那以后,工具或SDK有没有变化?看起来您使用的是新的现代IDL 3语法。我忘了澄清示例。一个只有当公共构造函数尝试合成所需的接口时,它对类型系统有一些模糊性。因此,如果您没有向类型添加任何成员,则需要指定
[default\u interface]
attribute。我应该澄清这在官方17134 SDK中是有效的。我还没有使用17125预览SDK进行测试,我不能说预览版和发行版之间是否存在一些细微的差异。最好使用支持的版本。:)这是一个疏忽,抱歉,我使用的是官方17134 SDK(如问题中的错误消息所示)。无论如何,使用
[默认\u界面]
attribute确实修复了MIDL错误,并生成了具有预期内容的文件。虽然我了解COM聚合,但我仍然对C++/WinRT使用的聚合类型的剖析感到非常困惑。是否有机会发布关于这些内部结构的文档?我知道这相当于记录实现细节虽然有C++编译器的诊断故事,但这些细节还是表面的。好的。我将把它转发到我们正在进行的文档工作中。因为正如你所说的,它是实现细节,我不完全确定文档将在哪里生存,或者它看起来会是什么样子,但是我同意某种支持信息。应该在那里。
namespace MyApp
{
  [default_interface]
  runtimeclass MyControl : Windows.UI.Xaml.Controls.Control
  {
    MyControl();
  };
}