如何以两种方式绑定到 UserControl DependencyProperty?
How to two way bind to a UserControl DependencyProperty?
我正在使用 UserControl
制作一个名为 scalar_slider
的自定义滑块。我想通过两种方式绑定其中之一 DependencyProperty
.
问题是在 scalar_slider
中所做的值更改不会更新回正确实现 INotifyPropertyChanged
的父视图模型 vm
。我认为问题与我在 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);
}
}
关于你的代码,我发现你写的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"));
}
我正在使用 UserControl
制作一个名为 scalar_slider
的自定义滑块。我想通过两种方式绑定其中之一 DependencyProperty
.
问题是在 scalar_slider
中所做的值更改不会更新回正确实现 INotifyPropertyChanged
的父视图模型 vm
。我认为问题与我在 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);
}
}
关于你的代码,我发现你写的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"));
}