Как сделать двустороннюю привязку к UserControl DependencyProperty? - PullRequest
1 голос
/ 05 июня 2019

Я делаю пользовательский слайдер с именем scalar_slider, используя UserControl. Я хотел бы связать одно из двух DependencyProperty.

Проблема в том, что изменения значений, сделанные внутри scalar_slider, не обновляются до модели представления родителя vm, которая правильно реализует INotifyPropertyChanged. Я предполагаю, что проблема связана с тем, как я устанавливаю привязку в MainPage.xaml.

// MainPage.xaml

 <local:scalar_slider scalar_value="{x:Bind vm.my_scalar_value Mode=TwoWay}" /> 

// scalar_slider.xaml

<UserControl
    x:Class="transformations.scalar_slider"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:transformations"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"> 
    <StackPanel>
        <TextBox Text="{x:Bind scalar_value, Mode=TwoWay}"/>
        <Slider Value="{x:Bind scalar_value, Mode=TwoWay}"/>
    </StackPanel>
</UserControl>

// scalar_slider.idl

namespace transformations
{
    [default_interface]
    runtimeclass scalar_slider : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        scalar_slider();    
        static Windows.UI.Xaml.DependencyProperty scalar_valueProperty;
        Single scalar_value;
    }
}

// scalar_slider.h

namespace winrt::transformations::implementation
{
    struct scalar_slider : scalar_sliderT<scalar_slider>
    {
        scalar_slider();

        static Windows::UI::Xaml::DependencyProperty scalar_valueProperty();
        static void scalar_valueProperty(Windows::UI::Xaml::DependencyProperty value);

        float scalar_value();
        void scalar_value(float value);

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

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

    private:
        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));
        }

        static Windows::UI::Xaml::DependencyProperty m_scalar_value_property;

        float m_scalar_value = 0.0f;
    };
}

// scalar_slider.cpp

namespace winrt::transformations::implementation
{
    scalar_slider::scalar_slider()
    {
        InitializeComponent();
    }

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

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

    Windows::UI::Xaml::DependencyProperty scalar_slider::m_scalar_value_property = Windows::UI::Xaml::DependencyProperty::Register(
        L"scalar_value",
        winrt::xaml_typename<float>(),
        winrt::xaml_typename<winrt::transformations::scalar_slider>(),
        Windows::UI::Xaml::PropertyMetadata{ nullptr }
    );

    Windows::UI::Xaml::DependencyProperty scalar_slider::scalar_valueProperty()
    {
        return m_scalar_value_property;
    }

    void scalar_slider::scalar_valueProperty(Windows::UI::Xaml::DependencyProperty value)
    {
        m_scalar_value_property = value;
    }

    float scalar_slider::scalar_value()
    {
        return m_scalar_value;
    }

    void scalar_slider::scalar_value(float value)
    {
        update_value(L"scalar_value", m_scalar_value, value);
    }
}

1 Ответ

3 голосов
/ 05 июня 2019

Что касается вашего кода, я считаю, что функция get и set свойства scalar_slider, которое вы пишете, неверна в scalar_slider.cpp, вы можете изменить их, как показано ниже.

Вы также можете прочитать Пользовательские (шаблонные) элементы управления XAML с помощью C ++ / WinRT , чтобы лучше понять.

float scalar_slider::scalar_value()
{​
    return winrt::unbox_value<float>(GetValue(m_scalar_value_property));​
}​
​
void scalar_slider::scalar_value(float value)​
{​
    SetValue(m_scalar_value_property, winrt::box_value(value));​
    m_property_changed(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs(L"scalar_value"));​
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...