Why does the binding get updated only once in WPF user control?

By Mirek on (tags: dependency property, user control, WPF, categories: code)

Recently I struggled on my user control trying to make the dependency property be updated when I change the source of the binding. That confirmed my belief that WPF does not forgive any single developer’s mistake.

For the sake of this post I simplified the code. The code of the user control was something like this

   1: public partial class MyControl : UserControl
   2: {
   4:     public double Value
   5:     {
   6:         get { return (double)GetValue(ValueProperty); }
   7:         set { SetValue(ValueProperty, value); }
   8:     }
  10:     public static readonly DependencyProperty ValueProperty =
  11:         DependencyProperty.Register("Value", typeof(double), typeof(MyControl),
  12:         new FrameworkPropertyMetadata(0.0,new PropertyChangedCallback(ValueChanged)));
  14:     private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  15:     {
  16:         ((MyControl)d).Value = Math.Round(((MyControl)d).Value, 1);
  17:         ((MyControl)d).Rearrange();
  18:     }
  20:     public void Rearrange()
  21:     {
  22:         ...
  23:     }

And the xaml, here I use this control was like this

<uc:MyControl  Value="{Binding Path=PercentageValue}" />

Simple, nothing special.
The problem was that the dependency property Value was always set once and stayed unchanged, no matter how many time I change the PercentageValue. INotifyPropertyChange event was raised properly, binding settings worked as well. Using any standard control, like TextBlock or TextBox worked perfectly.

Finally I’ve found the answer in documentation. The reason the binding was broken was my ValueChanged callback method where the value of dependency property was overwritten (line 16). In terms of dependency property any value set from the code is called a local value and as said on msdn setting a local value breaks the binding of the dependency property. You can read more about it in the documentation, especially the paragraph titled Bindings and precedence. Everything I had to do was to modify my user control code so it does not overwrite the value of dependency property.