Я делаю собственный слайдер под названием 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);
}
}





Что касается вашего кода, я считаю, что функция получения и установки свойства 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"));
}
Из предоставленного вами связь: «Если вам нужен DP с типом с плавающей запятой, сделайте его double (Double в MIDL 3.0). Объявление и реализация DP типа float (Single в MIDL), а затем установка значения для этого DP в разметке XAML, приводит к ошибке Не удалось создать «Windows.Foundation.Single» из текста «».."
Я использую поплавок прямо сейчас, и он, кажется, работает нормально. Может это устарело? Я не заметил никаких ошибок.
Какое определение для
vm(в частности, его свойстваmy_scalar_value)?