I have a control with a DependencyProperty with a CoerceValueCallback. This property is bound to a property on a model object.
When setting the control property to a value that causes coercion the Binding pushes the uncoerced value to the model object. The property value on the control is coerced correctly.
How do I get the Binding to push the coerced value to the model object?
void Initialize() { UIObject ui = new UIObject(); ModelObject m = new ModelObject(); m.P = 4; Binding b = new Binding('P'); b.Source = m; b.Mode = BindingMode.TwoWay; Debug.WriteLine('SetBinding'); // setting the binding will push the model value to the UI ui.SetBinding(UIObject.PProperty, b); // Setting the UI value will result in coercion but only in the UI. // The value pushed to the model through the binding is not coerced. Debug.WriteLine('Set to -4'); ui.P = -4; Debug.Assert(ui.P == 0); // The binding is TwoWay, the DP value is coerced to 0. Debug.Assert(m.P == 0); // Not true. This will be -4. Why??? } class UIObject : FrameworkElement { public static readonly DependencyProperty PProperty = DependencyProperty.Register('P', typeof(int), typeof(UIObject), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnPChanged), new CoerceValueCallback(CoerceP))); public int P { get { return (int)GetValue(PProperty); } set { SetValue(PProperty, value); } } private static void OnPChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Debug.WriteLine(typeof(UIObject) + '.P changed from ' + e.OldValue + ' to ' + e.NewValue); } private static object CoerceP(DependencyObject sender, object value) { int p = (int)value; if (p < 0) { Debug.WriteLine(typeof(UIObject) + '.P coerced from ' + p + ' to 0'); p = 0; } return p; } } class ModelObject { private int p; public int P { get { Debug.WriteLine(this + '.P returned ' + this.p); return this.p; } set { Debug.WriteLine(this + '.P changed from +' + this.p + ' to ' + value); this.p = value; } } }
I don’t think the coerce callback is meant to be a two-way street. One workaround would be to update the model’s value inside of the coerce callback.