如何使 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。它公开了一个名为 ValueDependencyProperty,并在 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);