Как TwoWay связать UserControl в UWP XAML?(C ++ / WinRT) - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь выполнить двустороннее связывание данных внутри UserControl.Приведенный ниже код работает для одностороннего связывания, но когда я пытаюсь использовать двухстороннее связывание, я получаю следующую ошибку от компилятора xaml:

XamlCompiler error WMC1118: TwoWay binding target 'value_prop' must be a dependency property  

Однако меня это очень смущает, потому что я сделал value_propсвойство зависимости.Как я могу сделать эту работу?

// MainPage.xaml

  <local:attribute_slider Label="Scale" value_prop="{x:Bind texture_showcase_vm.current_texture.scale, Mode=TwoWay}"/>

// attribute_slider.xaml

<UserControl
    x:Class="wzrd_editor.attribute_slider"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:wzrd_editor"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" >
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" >
        <TextBlock x:Name="scale_label" Text="{x:Bind Label, Mode=OneWay}" HorizontalAlignment="Left" />
        <TextBlock x:Name="scale_text_value" Text="{x:Bind value_prop, Mode=TwoWay}" HorizontalAlignment="Right"
                                       RelativePanel.AlignRightWithPanel="True"
                                       RelativePanel.RightOf="scale_label" />

        <Slider x:Name="Scale" Value="{x:Bind value_prop, Mode=TwoWay}" Width="200" Orientation="Horizontal" Minimum="0" Maximum="10" StepFrequency="0.01" TickFrequency="0.01" SnapsTo="StepValues" TickPlacement="None"
                                   RelativePanel.Below="scale_label" 
                                   RelativePanel.AlignRightWith="scale_text_value"
                                   RelativePanel.AlignLeftWith="scale_label"
                                   RelativePanel.AlignRightWithPanel="True" />

    </StackPanel>
</UserControl>

// attribute_slider.idl

namespace wzrd_editor
{
    [bindable]
    [default_interface]
    runtimeclass attribute_slider : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        attribute_slider();
        static Windows.UI.Xaml.DependencyProperty LabelProperty{ get; };
        static Windows.UI.Xaml.DependencyProperty value_property{ get; set; };
        String Label;
        Single value_prop;
    }
}

attribute_slider.h

namespace winrt::wzrd_editor::implementation
{
    struct attribute_slider : attribute_sliderT<attribute_slider>
    {
        attribute_slider();

        static Windows::UI::Xaml::DependencyProperty LabelProperty();
        static Windows::UI::Xaml::DependencyProperty value_property();
        static void value_property(Windows::UI::Xaml::DependencyProperty const& value);

        hstring Label();
        void Label(hstring const& value);

        float value_prop();
        void value_prop(float const& value);

        winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
        void PropertyChanged(winrt::event_token const& token) noexcept;

    private:
        static Windows::UI::Xaml::DependencyProperty m_labelProperty;
        static Windows::UI::Xaml::DependencyProperty m_value_property;
        hstring m_label = L"";
        float m_value = 0.0f;

        winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_property_changed;

        void raise_property_changed(hstring const& property_name)
        {
            m_property_changed(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs(property_name));
        }

        template <class T>
        void update_value(hstring const& property_name, T & var, T value)
        {
            if (var != value)
            {
                var = value;
                raise_property_changed(property_name);
            }
        }
    };
}

// attribute_slider.cpp

namespace winrt::wzrd_editor::implementation
{
    Windows::UI::Xaml::DependencyProperty attribute_slider::m_labelProperty =
        Windows::UI::Xaml::DependencyProperty::Register(
            L"Label",
            winrt::xaml_typename<winrt::hstring>(),
            winrt::xaml_typename<wzrd_editor::attribute_slider>(),
            Windows::UI::Xaml::PropertyMetadata{ nullptr }
    );

    Windows::UI::Xaml::DependencyProperty attribute_slider::m_value_property =
        Windows::UI::Xaml::DependencyProperty::Register(
            L"value_prop",
            winrt::xaml_typename<winrt::hstring>(),
            winrt::xaml_typename<wzrd_editor::attribute_slider>(),
            Windows::UI::Xaml::PropertyMetadata{ nullptr }
    );

    attribute_slider::attribute_slider()
    {
        InitializeComponent();
    }

    hstring attribute_slider::Label()
    {
        return m_label;
    }

    void attribute_slider::Label(hstring const& value)
    {
        update_value(L"Label", m_label, value);
    }

    float attribute_slider::value_prop()
    {
        return m_value;
    }

    void attribute_slider::value_prop(float const& value)
    {
        update_value(L"value_prop", m_value, value);
    }

    Windows::UI::Xaml::DependencyProperty attribute_slider::LabelProperty()
    {
        return m_labelProperty;
    }

    Windows::UI::Xaml::DependencyProperty attribute_slider::value_property()
    {
        return m_value_property;
    }

    void attribute_slider::value_property(Windows::UI::Xaml::DependencyProperty const& value)
    {
        m_value_property = value;
    }

    winrt::event_token attribute_slider::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
    {
        return m_property_changed.add(handler);
    }

    void attribute_slider::PropertyChanged(winrt::event_token const& token) noexcept
    {
        m_property_changed.remove(token);
    }
}
...