如何两种方式绑定到UserControl DependencyProperty?

时间:2019-06-05 00:56:54

标签: xaml uwp uwp-xaml c++-winrt

我正在使用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 个答案:

答案 0 :(得分:3)

关于您的代码,我发现您编写的scalar_slider属性的get和set函数在scalar_slider.cpp中不正确,您可以像下面的代码一样更改它们。

您也可以阅读XAML custom (templated) controls with 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"));​
}