title: Force Propagation of Coerced Value
body: <p><strong>tl;dr: Coerced values are not propagated across data bindings. How can I force the update across the data binding when code-behind doesn't know the other side of the binding?</strong></p>
  
  <hr>
  
  <p>I'm using a <code>CoerceValueCallback</code> on a WPF dependency property and I'm stuck at the issue that coerced values don't get propagated through to bindings.</p>
  
  <p><strong>Window1.xaml.cs</strong></p>
  
  <pre><code>using System;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Data;
  using System.Windows.Media;
  
  namespace CoerceValueTest
  {
      public class SomeControl : UserControl
      {
          public SomeControl()
          {
              StackPanel sp = new StackPanel();
  
              Button bUp = new Button();
              bUp.Content = "+";
              bUp.Click += delegate(object sender, RoutedEventArgs e) {
                  Value += 2;
              };
  
              Button bDown = new Button();
              bDown.Content = "-";
              bDown.Click += delegate(object sender, RoutedEventArgs e) {
                  Value -= 2;
              };
  
              TextBlock tbValue = new TextBlock();
              tbValue.SetBinding(TextBlock.TextProperty,
                                 new Binding("Value") {
                                  Source = this
                                 });
  
              sp.Children.Add(bUp);
              sp.Children.Add(tbValue);
              sp.Children.Add(bDown);
  
              this.Content = sp;
          }
  
          public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value",
                                                                                                typeof(int),
                                                                                                typeof(SomeControl),
                                                                                                new PropertyMetadata(0, ProcessValueChanged, CoerceValue));
  
          private static object CoerceValue(DependencyObject d, object baseValue)
          {
              if ((int)baseValue % 2 == 0) {
                  return baseValue;
              } else {
                  return DependencyProperty.UnsetValue;
              }
          }
  
          private static void ProcessValueChanged(object source, DependencyPropertyChangedEventArgs e)
          {
              ((SomeControl)source).ProcessValueChanged(e);
          }
  
          private void ProcessValueChanged(DependencyPropertyChangedEventArgs e)
          {
              OnValueChanged(EventArgs.Empty);
          }
  
          protected virtual void OnValueChanged(EventArgs e)
          {
              if (e == null) {
                  throw new ArgumentNullException("e");
              }
  
              if (ValueChanged != null) {
                  ValueChanged(this, e);
              }
          }
  
          public event EventHandler ValueChanged;
  
          public int Value {
              get {
                  return (int)GetValue(ValueProperty);
              }
              set {
                  SetValue(ValueProperty, value);
              }
          }
      }
  
      public class SomeBiggerControl : UserControl
      {
          public SomeBiggerControl()
          {
              Border parent = new Border();
              parent.BorderThickness = new Thickness(2);
              parent.Margin = new Thickness(2);
              parent.Padding = new Thickness(3);
              parent.BorderBrush = Brushes.DarkRed;
  
              SomeControl ctl = new SomeControl();
              ctl.SetBinding(SomeControl.ValueProperty,
                             new Binding("Value") {
                              Source = this,
                              Mode = BindingMode.TwoWay
                             });
              parent.Child = ctl;
  
              this.Content = parent;
          }
  
          public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value",
                                                                                                typeof(int),
                                                                                                typeof(SomeBiggerControl),
                                                                                                new PropertyMetadata(0));
  
          public int Value {
              get {
                  return (int)GetValue(ValueProperty);
              }
              set {
                  SetValue(ValueProperty, value);
              }
          }
      }
  
      public partial class Window1 : Window
      {
          public Window1()
          {
              InitializeComponent();
          }
      }
  }
  </code></pre>
  
  <p><strong>Window1.xaml</strong></p>
  
  <pre><code>&lt;Window x:Class="CoerceValueTest.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="CoerceValueTest" Height="300" Width="300"
      xmlns:local="clr-namespace:CoerceValueTest"
      &gt;
      &lt;StackPanel&gt;
          &lt;local:SomeBiggerControl x:Name="sc"/&gt;
          &lt;TextBox Text="{Binding Value, ElementName=sc, Mode=TwoWay}" Name="tb"/&gt;
          &lt;Button Content=" "/&gt;
      &lt;/StackPanel&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>i.e. two user controls, one nested inside the other, and the outer one of those in a window. The inner user control has a <code>Value</code> dependency property that is bound to a <code>Value</code> dependency property of the outer control. In the window, a <code>TextBox.Text</code> property is bound to the <code>Value</code> property of the outer control.</p>
  
  <p>The inner control has a <code>CoerceValueCallback</code> registered with its <code>Value</code> property whose effect is that this <code>Value</code> property can only be assigned even numbers.</p>
  
  <p><em>Note that this code is simplified for demonstration purposes. The real version doesn't initialize anything in the constructor; the two controls actually have control templates that do everything that's done in the respective constructors here. That is, in the real code, the outer control doesn't know the inner control.</em></p>
  
  <p>When writing an even number into the text box and changing the focus (e.g. by focusing the dummy button below the text box), both <code>Value</code> properties get duly updated. When writing an odd number into the text box, however, the <code>Value</code> property of the inner control doesn't change, while the <code>Value</code> property of the outer control, as well as the <code>TextBox.Text</code> property, show the odd number.</p>
  
  <p>My question is: <strong>How can I force an update in the text box (and ideally also in the outer control's <code>Value</code> property, while we're at it)?</strong></p>
  
  <p>I have found <a href="https://stackoverflow.com/questions/3323461/why-does-my-data-binding-see-the-real-value-instead-of-the-coerced-value">an SO question on the same problem</a>, but doesn't really provide a solution. It alludes to using a property changed event handler to reset the value, but as far as I can see, that would mean duplicating the evaluation code to the outer control ... which is not really viable, as my actual evaluation code relies on some information basically only known (without much effort) to the inner control.</p>
  
  <p>Moreover, <a href="http://dotnetlearning.wordpress.com/2010/10/05/textbox-binding-coercevalue/" rel="noreferrer">this blogpost</a> suggests invoking <code>UpdateTarget</code> on the binding in <code>TextBox.Text</code> in the <code>CoerceValueCallback</code>, but first, as implied above, my inner control cannot possibly have any knowledge about the text box, and second, I would probably have to call <code>UpdateSource</code> first on the binding of the <code>Value</code> property of the inner control. I don't see where to do that, though, as within the <code>CoerceValue</code> method, the coerced value has not yet been set (so it's too early to update the binding), while in the case that the value is reset by <code>CoerceValue</code>, the property value will just remain what it was, hence a property changed callback will not get invoked (as also implied in <a href="http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/cc2f0fe3-a7b3-4f17-8915-a72a41fe4729/" rel="noreferrer">this discussion</a>).</p>
  
  <p>One possible workaround I had thought of was replacing the dependency property in <code>SomeControl</code> with a conventional property and an <code>INotifyPropertyChanged</code> implementation (so I can manually trigger the <code>PropertyChanged</code> event even if the value has been coerced). However, this would mean that I cannot declare a binding on that property any more, so it's not a really useful solution.</p>