在 C++/WinRT 中实现自定义 XAML DependencyProperty 的最低要求是多少?

问题描述 投票:0回答:1

我正在编写 WinUI 3 和 UWP 代码,并且我想要一个带有 DependencyProperty 的自定义控件:

<local:MyControl Foo="Bar" />

我已经阅读了 MSDN 上的自定义依赖属性,但是那里有很多内容。使用 C++/WinRT 在 UWP 或 WinUI XAML 中实现自定义 DependencyProperty 所需的最低限度的简短示例是什么?

uwp winui-3 c++-winrt winui
1个回答
0
投票

这是我对自定义依赖属性的提炼,无论如何它都值得一读,因为它解释了依赖属性的许多细微差别:

IDL

  1. 添加一个名为
    FooProperty
    类型为
    static Microsoft.UI.Xaml.DependencyProperty
  2. 的静态 getter
  3. 添加您想要的实际类型的名为
    Foo
    的 getter 和 setter。
// MyControl.idl
runtimeclass MyControl : Microsoft.UI.Xaml.Controls.UserControl
{
    MyControl(); // ... etc

    // Add these for each property
    static Microsoft.UI.Xaml.DependencyProperty FooProperty{ get; };
    String Foo;
}

C++

  1. 使用
    DependencyObject::GetValue
    SetValue
    实现成员 getter 和 setter(应通过 UserControl 等继承)。
  2. 实现静态 DependencyProperty getter,您可以对其进行配置,以便您的属性可以具有默认值和属性更改处理程序。
  3. 确保
    Register
    您的依赖属性。
// MyControl.h
namespace winrt::MyAppNamespace::implementation
{
    struct MyControl : MyControlT<MyControl>
    {
        // ...

        static winrt::Microsoft::UI::Xaml::DependencyProperty FooProperty() const noexcept
        {
            return s_FooProperty;
        }
        auto Foo() const noexcept
        {
            return winrt::unbox_value<winrt::hstring>(GetValue(FooProperty()));
        }
        void Foo(winrt::hstring const& value)
        {
            SetValue(FooProperty(), winrt::box_value(value));
        }

    private:
        static winrt::Microsoft::UI::Xaml::DependencyProperty s_FooProperty;
    }
}

// MyControl.cpp
using namespace winrt::MyAppNamespace::implementation;

MyControl::s_FooProperty =
    winrt::Microsoft::UI::Xaml::DependencyProperty::Register(
        L"Foo",
        winrt::xaml_typename<winrt::hstring>(),
        winrt::xaml_typename<winrt::MyAppNamespace::MyControl>(),
        winrt::Microsoft::UI::Xaml::PropertyMetadata{nullptr});

完成!您现在拥有一个有效的依赖属性:

<MyControl Foo="Bar!" />

默认值和更改的处理程序

  • 如果您想要静态的“更改时”回调,请向
    PropertyMetadata
    构造函数添加第二个参数。
  • 如果您想要默认值,请将第一个参数更改为您的默认值。
// Value-changed callback
MyControl::s_FooProperty =
    winrt::Microsoft::UI::Xaml::DependencyProperty::Register(
        L"Foo",
        winrt::xaml_typename<winrt::hstring>(),
        winrt::xaml_typename<winrt::MyAppNamespace::MyControl>(),
        winrt::Microsoft::UI::Xaml::PropertyMetadata{nullptr, &MyControl::OnFooChanged});

// Value-changed callback & default value
MyControl::s_FooProperty =
    winrt::Microsoft::UI::Xaml::DependencyProperty::Register(
        L"Foo",
        winrt::xaml_typename<winrt::hstring>(),
        winrt::xaml_typename<winrt::MyAppNamespace::MyControl>(),
        winrt::Microsoft::UI::Xaml::PropertyMetadata{winrt::box_value(L"Default value"), &MyControl::OnFooChanged});

注意回调是静态的,而不是成员函数。您必须获取实际实例:

/*static*/ void MyControl::OnFooChanged(winrt::Microsoft::UI::Xaml::DependencyObject const& d, winrt::Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& e)
{
    auto control{ d.as<MyAppNamespace::MyControl>() };
    auto newValue{ winrt::unbox_value<winrt::hstring>(e.NewValue()) };
}

另请参阅

© www.soinside.com 2019 - 2024. All rights reserved.