How to create a XAML custom control in code?

大兔子大兔子 提交于 2019-12-12 14:23:49

问题


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

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.

What is required to implement a XAML custom control in code?


回答1:


"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.

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&);
    };
}

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.

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();
  };
}

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.

(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.



来源:https://stackoverflow.com/questions/50824870/how-to-create-a-xaml-custom-control-in-code

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!