title: Text on TextBox with UpdateSourceTrigger=PropertyChanged is not updated when coercion of text input results in unchanged source value
body: <p>I have a text box whose <strong>Text</strong> property has a <strong>TwoWay</strong> <em>MultiBinding</em> with <strong>UpdateSourceTrigger</strong> set to <strong>PropertyChanged</strong>. The first <em>Binding</em> is to a dependency property (<strong>Value</strong>) which has a <em>PropertyChangedCallBack</em> function that rounds the value to one decimal place.</p>
  
  <p>The purpose of the text box is to perform the rounding as the user types rather than when the text box loses focus, hence why <strong>UpdateSourceTrigger</strong> is set to <strong>PropertyChanged</strong>.</p>
  
  <p>The problem I am having is that if text is entered that does NOT result in <strong>Value</strong> changing, the <strong>Text</strong> property and <strong>Value</strong> become out of sync. Only if the rounding operation causes <strong>Value</strong> to change does <strong>Text</strong> get updated on the fly. E.g., if <strong>Text</strong> and <strong>Value</strong> are both 123.4 and the user types 1 after this, <strong>Value</strong> is rounded to the same value (123.4), but <strong>Text</strong> shows 123.41. However, if 9 is then typed after the 4, <strong>Value</strong> is rounded up to 123.5. And because of this actual change, <strong>Text</strong> is then updated to the same (123.5).</p>
  
  <p>Is there any way of forcing a text box to update from its source even when the source hasn't changed since the last trigger? I have tried using <code>BindingExpressionBase.UpdateTarget()</code> but this only works when <strong>UpdateSourceTrigger</strong> is set to <strong>Explicit</strong>, which can't be used as <strong>Value</strong> no longer gets updated prior to a suitable time where <strong>UpdateTarget</strong> could be called (such as a <em>TextInput</em> handler). I have tried other methods such as explicitly updating the <strong>Text</strong> value from the bound <strong>Value</strong>, forcing an actual change to <strong>Value</strong> temporarily to invoke an update, but these "hacks" either don't work or cause other problems.</p>
  
  <p>Any help would be greatly appreciated.</p>
  
  <p>The code is below.</p>
  
  <h2>XAML snippet</h2>
  
  <pre><code>&lt;TextBox&gt;
    &lt;TextBox.Text&gt;
      &lt;MultiBinding Converter="{local:NumberFormatConverter}"
                    UpdateSourceTrigger="Explicit"
                    Mode="TwoWay"&gt;
        &lt;Binding Path="Value"
                 RelativeSource="{RelativeSource AncestorType={x:Type Window}}"
                 Mode="TwoWay" /&gt;
      &lt;/MultiBinding&gt;
    &lt;/TextBox.Text&gt;
  &lt;/TextBox&gt;
  </code></pre>
  
  <h2>C# snippet</h2>
  
  <pre><code>public static readonly DependencyProperty ValueProperty =
      DependencyProperty.Register(
          "Value", typeof(decimal), typeof(MainWindow),
          new FrameworkPropertyMetadata(0m,
          new PropertyChangedCallback(OnValueChanged)));
  
  private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
  {
      obj.SetValue(ValueProperty, Math.Round((decimal)args.NewValue, 1));
  }
  </code></pre>
  
  <h2>Converter class required</h2>
  
  <pre><code>public class NumberFormatConverter : MarkupExtension, IMultiValueConverter
  {
      public static NumberFormatConverter Instance { private set; get; }
  
      static NumberFormatConverter()
      {
          Instance = new NumberFormatConverter();
      }
  
      public override object ProvideValue(IServiceProvider serviceProvider_)
      {
          return Instance;
      }
  
      #region Implementation of IMultiValueConverter
  
      public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
      {
          return values[0].ToString();
      }
  
      public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
      {
          var result = 0m;
          if (value != null)
          {
              decimal.TryParse(value.ToString(), out result);
          }
          return new object[] { result };
      }
  
      #endregion
  }
  </code></pre>