如何使 DependencyProperty 正确强制绑定值的类型
How to make a DependencyProperty properly coerce a value's type for a binding
我有一个 ItemsControl
子class,它的行为类似于 Selector
,但它不能是 Selector
的子class因为所选项目不一定在 Items
集合中。所以我不得不重新实现很多 Selector
东西。
我的 class 有一个 SelectedValuePath
属性。如果 属性 有一个值,我创建一个绑定,以便当 SelectedItem
更改时,"SelectedItem." + SelectedValuePath
的值被分配给 SelectedValue
。这非常有效——只要消费者将我的 SelectedValue
绑定到与 [=16 上的值 属性 相同类型 的 属性 =].
问题来了:
但是,如果所选项目有一个 int ID
属性 用作值 属性,并且 SelectedValue
绑定到 Nullable<int> SelectedID
属性 在视图模型上,绑定无法在视图模型上设置 属性,除非 SelectedItem
为 null。
我注意到 WPF ComboBox
class 没有这个问题,所以它必须是可以解决的,不需要消费者提供值转换器。我已经尝试了 CoerceValueCallback
,但这对我没有任何作用。它不知道目标类型。它没有关于接收值的绑定的信息。
什么是 ComboBox.SelectedValue
而我没有做的事情?
我相当熟悉 IValueConverter
以及如何在使用控件时将值转换器添加到 XAML 中的绑定。我不需要帮助。我问是否有人知道 ComboBox.SelectedValue
上的任何绑定如何将 int
转换为 int?
而无需控件的使用者向绑定添加值转换器。
如我所料,问题出在我的预料之外。没有类型转换问题。
看来问题出在我的 class 内部。我正在使用绑定更新 SelectedValue
。
Binding binding = new Binding("SelectedItem." + SelectedValuePath);
binding.Mode = BindingMode.OneWay;
binding.Source = this;
BindingOperations.SetBinding(this, MenuComboBox.SelectedValueProperty, binding);
这似乎干扰了消费者对 SelectedValue
的双向绑定。
我有一个 BindingTarget
class 派生自 DependencyObject
。它公开了一个名为 Value
的 DependencyProperty
,并在 Value
更改时触发一个事件。我已经写了它来将值转发到 "read only" DependencyProperty
SelectionBoxItem
,其中 setter 受到保护。因此,我没有像上面那样以 SelectedValue
作为目标从 "SelectedItem."+SelectedValuePath
创建绑定,而是使用私有 BindingTarget
实例作为目标,并在其 [=25] 中设置 SelectedValue
=] 处理程序。消费者的绑定现在按预期工作。
// The type argument to BindingTarget is the type of the property.
_selectedValueBindingTarget = new BindingTarget<Object>();
_selectedValueBindingTarget.ValueChanged += (s, e2) =>
{
SelectedValue = e2.NewValue;
};
Binding binding = new Binding("SelectedItem." + SelectedValuePath);
binding.Mode = BindingMode.OneWay;
binding.Source = this;
BindingOperations.SetBinding(_selectedValueBindingTarget,
BindingTarget<Object>.ValueProperty, binding);
我有一个 ItemsControl
子class,它的行为类似于 Selector
,但它不能是 Selector
的子class因为所选项目不一定在 Items
集合中。所以我不得不重新实现很多 Selector
东西。
我的 class 有一个 SelectedValuePath
属性。如果 属性 有一个值,我创建一个绑定,以便当 SelectedItem
更改时,"SelectedItem." + SelectedValuePath
的值被分配给 SelectedValue
。这非常有效——只要消费者将我的 SelectedValue
绑定到与 [=16 上的值 属性 相同类型 的 属性 =].
问题来了:
但是,如果所选项目有一个 int ID
属性 用作值 属性,并且 SelectedValue
绑定到 Nullable<int> SelectedID
属性 在视图模型上,绑定无法在视图模型上设置 属性,除非 SelectedItem
为 null。
我注意到 WPF ComboBox
class 没有这个问题,所以它必须是可以解决的,不需要消费者提供值转换器。我已经尝试了 CoerceValueCallback
,但这对我没有任何作用。它不知道目标类型。它没有关于接收值的绑定的信息。
什么是 ComboBox.SelectedValue
而我没有做的事情?
我相当熟悉 IValueConverter
以及如何在使用控件时将值转换器添加到 XAML 中的绑定。我不需要帮助。我问是否有人知道 ComboBox.SelectedValue
上的任何绑定如何将 int
转换为 int?
而无需控件的使用者向绑定添加值转换器。
如我所料,问题出在我的预料之外。没有类型转换问题。
看来问题出在我的 class 内部。我正在使用绑定更新 SelectedValue
。
Binding binding = new Binding("SelectedItem." + SelectedValuePath);
binding.Mode = BindingMode.OneWay;
binding.Source = this;
BindingOperations.SetBinding(this, MenuComboBox.SelectedValueProperty, binding);
这似乎干扰了消费者对 SelectedValue
的双向绑定。
我有一个 BindingTarget
class 派生自 DependencyObject
。它公开了一个名为 Value
的 DependencyProperty
,并在 Value
更改时触发一个事件。我已经写了它来将值转发到 "read only" DependencyProperty
SelectionBoxItem
,其中 setter 受到保护。因此,我没有像上面那样以 SelectedValue
作为目标从 "SelectedItem."+SelectedValuePath
创建绑定,而是使用私有 BindingTarget
实例作为目标,并在其 [=25] 中设置 SelectedValue
=] 处理程序。消费者的绑定现在按预期工作。
// The type argument to BindingTarget is the type of the property.
_selectedValueBindingTarget = new BindingTarget<Object>();
_selectedValueBindingTarget.ValueChanged += (s, e2) =>
{
SelectedValue = e2.NewValue;
};
Binding binding = new Binding("SelectedItem." + SelectedValuePath);
binding.Mode = BindingMode.OneWay;
binding.Source = this;
BindingOperations.SetBinding(_selectedValueBindingTarget,
BindingTarget<Object>.ValueProperty, binding);