使用 XAML 和 C++/WinRT 时,properties/functions 必须在 IDL 中加入什么?

What properties/functions have to go in an IDL when using XAML and C++/WinRT?

我为用 C++/WinRT 编写的自定义 XAML 控件编写的 IDL 中必须包含什么 properties/functions/anything?

例子

当我在 Visual Studio 中创建自定义 C++/WinRT XAML 控件时,它会创建 4 个文件:

IDL 文件是基本的,包括一个简单的 属性:

namespace MyNamespace
{
    [default_interface]
    runtimeclass MyControl : Windows.UI.Xaml.Controls.UserControl
    {
        MyControl();
        Int32 MyProperty;
    }
}

有趣的是,.h文件除了这个属性之外还包含另一个函数:

#pragma once

#include "winrt/Windows.UI.Xaml.h"
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.Xaml.Interop.h"
#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
#include "MyControl.g.h"

namespace winrt::MyNamespace::implementation
{
    struct MyControl : MyControlT<MyControl>
    {
        MyControl();

        int32_t MyProperty();
        void MyProperty(int32_t value);

        void ClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args);
    };
}

namespace winrt::MyNamespace::factory_implementation
{
    struct MyControl : MyControlT<MyControl, implementation::MyControl>
    {
    };
}

.xaml 绑定到没有问题:

<!-- ... -->
<Button x:Name="Button" Click="ClickHandler">Click Me</Button>
<!-- ... -->

问题

我不清楚何时需要在我的 IDL 上引入一个函数或 属性 以便在 XAML 中使用它。

是否所有属性都需要添加到 IDL 中?只是依赖属性?函数是否必须出现在 IDL 中?

为什么在 IDL 中出现 MyProperty 而不是 ClickHandler

谢谢!

简答:

Needs to be in IDL? Needs to be implemented in C++?
Property x:Bind ✅ Yes, the property must be exposed in the IDL. ✅ Yes, you must implement the property.
Binding ❌ No, but your control must implement ICustomPropertyProvider and ICustomProperty. See Using the {Binding} markup extension with C++/WinRT. (You must implement those interfaces, so yes)
Function Delegate ❌ No, the function simply needs to be public in your implementation. ✅ Yes, by definition you must implement the function you want to call.
x:Bind ✅ Yes, the function must be exposed in the IDL. ✅ Yes, by definition you must implement the function you want to call.
Element x:Bind ✅ Yes, the element must be exposed in the IDL. ❌ No, the implementation code will be auto-generated; don't write any C++.

或者另一种表达方式:

  • 任何使用 x:Bind 的东西都需要在 IDL 中。

    • 这包括一切x:Bind---属性和功能是显而易见的,而且元素(见Element-to-element binding).所以如果你想 x:Bind 一个 TextBlockContent 到一个 TextBoxText,你需要公开 TextBox在 IDL 中。
  • 其他一切都不需要在 IDL 中。


MSDN 的 XAML controls; bind to a C++/WinRT property 提供了完整的答案:

All entities consumed by using the XAML {x:Bind} markup extension must be exposed publicly in IDL. Furthermore, if XAML markup contains a reference to another element that's also in markup, then the getter for that markup must be present in IDL.

<Page x:Name="MyPage">
    <StackPanel>
        <CheckBox x:Name="UseCustomColorCheckBox" Content="Use custom color"
             Click="UseCustomColorCheckBox_Click" />
        <Button x:Name="ChangeColorButton" Content="Change color"
            Click="{x:Bind ChangeColorButton_OnClick}"
            IsEnabled="{x:Bind UseCustomColorCheckBox.IsChecked.Value, Mode=OneWay}"/>
    </StackPanel>
</Page>

The ChangeColorButton element refers to the UseCustomColorCheckBox element via binding. So the IDL for this page must declare a read-only property named UseCustomColorCheckBox in order for it to be accessible to binding.

The click event handler delegate for UseCustomColorCheckBox uses classic XAML delegate syntax, so that doesn't need an entry in the IDL; it just needs to be public in your implementation class. On the other hand, ChangeColorButton also has an {x:Bind} click event handler, which must also go into the IDL.

runtimeclass MyPage : Windows.UI.Xaml.Controls.Page
{
    MyPage();

    // These members are consumed by binding.
    void ChangeColorButton_OnClick();
    Windows.UI.Xaml.Controls.CheckBox UseCustomColorCheckBox{ get; };
}

You don't need to provide an implementation for the UseCustomColorCheckBox property. The XAML code generator does that for you.