Why does my data binding see the real value instead of the coerced value?

wpf dependency property binding
xamarin forms custom control bindable property
attached property in wpf
dependency property in wpf example
dependency property in wpf example code project
clr property
dependency property in wpf mvvm
bindableproperty.create is obsolete

I'm writing a real NumericUpDown/Spinner control as an exercise to learn custom control authoring. I've got most of the behavior that I'm looking for, including appropriate coercion. One of my tests has revealed a flaw, however.

My control has 3 dependency properties: Value, MaximumValue, and MinimumValue. I use coercion to ensure that Value remains between the min and max, inclusive. E.g.:

// In NumericUpDown.cs

public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register("Value", typeof(int), typeof(NumericUpDown), 
    new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, HandleValueChanged, HandleCoerceValue));

[Localizability(LocalizationCategory.Text)]
public int Value
{
    get { return (int)this.GetValue(ValueProperty); }
    set { this.SetCurrentValue(ValueProperty, value); }
}

private static object HandleCoerceValue(DependencyObject d, object baseValue)
{
    NumericUpDown o = (NumericUpDown)d;
    var v = (int)baseValue;

    if (v < o.MinimumValue) v = o.MinimumValue;
    if (v > o.MaximumValue) v = o.MaximumValue;

    return v;
}

My test is just to ensure that data binding works how I expect. I created a default wpf windows application and threw in the following xaml:

<Window x:Class="WpfApplication.MainWindow" x:Name="This"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:nud="clr-namespace:WpfCustomControlLibrary;assembly=WpfCustomControlLibrary"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <nud:NumericUpDown Value="{Binding ElementName=This, Path=NumberValue}"/>
        <TextBox Grid.Row="1" Text="{Binding ElementName=This, Path=NumberValue, Mode=OneWay}" />
    </Grid>
</Window>

with very simple codebehind:

public partial class MainWindow : Window
{
    public int NumberValue
    {
        get { return (int)GetValue(NumberValueProperty); }
        set { SetCurrentValue(NumberValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for NumberValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty NumberValueProperty =
        DependencyProperty.Register("NumberValue", typeof(int), typeof(MainWindow), new UIPropertyMetadata(0));     

    public MainWindow()
    {
        InitializeComponent();
    }
}

(I'm omitting the xaml for the control's presentation)

Now if I run this I see the value from the NumericUpDown reflected appropriately in the textbox, but if I type in a value that's out of range the out of range value gets displayed in the test textbox while the NumericUpDown shows the correct value.

Is this how coerced values are supposed to act? It's good that it's coerced in the ui, but I expected the coerced value to run through the databinding as well.

Wow, that is surprising. When you set a value on a dependency property, binding expressions are updated before value coercion runs!

If you look at DependencyObject.SetValueCommon in Reflector, you can see the call to Expression.SetValue halfway through the method. The call to UpdateEffectiveValue that will invoke your CoerceValueCallback is at the very end, after the binding has already been updated.

You can see this on framework classes as well. From a new WPF application, add the following XAML:

<StackPanel>
    <Slider Name="Slider" Minimum="10" Maximum="20" Value="{Binding Value, 
        RelativeSource={RelativeSource AncestorType=Window}}"/>
    <Button Click="SetInvalid_Click">Set Invalid</Button>
</StackPanel>

and the following code:

private void SetInvalid_Click(object sender, RoutedEventArgs e)
{
    var before = this.Value;
    var sliderBefore = Slider.Value;
    Slider.Value = -1;
    var after = this.Value;
    var sliderAfter = Slider.Value;
    MessageBox.Show(string.Format("Value changed from {0} to {1}; " + 
        "Slider changed from {2} to {3}", 
        before, after, sliderBefore, sliderAfter));
}

public int Value { get; set; }

If you drag the Slider and then click the button, you'll get a message like "Value changed from 11 to -1; Slider changed from 11 to 10".

ValueChanging event and data binding, Wow, that is surprising. When you set a value on a dependency property, binding expressions are updated before value coercion runs! If you look at  However, when you have bound the ZoomLevel property to a property in your view model, the binding gets updated before the dependency property is coerced. (In that specific case, the binding is updated to 20 and only after that the property is coerced to 19) You can check out the following topic, where this wpf behavior is discussed: Why does my data binding see the real value instead of the coerced value?

A new answer for an old question: :-)

In the registration of the ValueProperty an FrameworkPropertyMetadata instance is used. Set the UpdateSourceTrigger property of this instance to Explicit. This can be done in a constructor overload.

public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register("Value", typeof(int), typeof(NumericUpDown), 
    new FrameworkPropertyMetadata(
      0, 
      FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, 
      HandleValueChanged, 
      HandleCoerceValue,
      false
      UpdateSourceTrigger.Explicit));

Now the binding source of the ValueProperty will not be updated automatically on PropertyChanged. Do the update manually in your HandleValueChanged method (see code above). This method is called only on 'real' changes of the property AFTER the coerce method has been called.

You can do it this way:

static void HandleValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
    NumericUpDown nud = obj as NumericUpDown;
    if (nud == null)
        return;

    BindingExpression be = nud.GetBindingExpression(NumericUpDown.ValueProperty);
    if(be != null)
        be.UpdateSource();
}

In this way you can avoid to update your bindings with non-coerced values of your DependencyProperty.

Dependency properties overview, Cancel property to true if the user chose not to confirm the change. I've come up with a workaround that seems to be working in my case (specifically, I'm listening for the SourceUpdated event instead and reverting the change NewValue % 2) == 1; // Cancel change if the new value is an odd number  Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app.

You are coercing v which is an int and as such a value type. It is therefore stored on the stack. It is in no way connected to baseValue. So changing v will not change baseValue.

The same logic applies to baseValue. It is passed by value (not by reference) so changing it will not change the actual parameter.

v is returned and is clearly used to update the UI.

You may want to investigate changing the properties data type to a reference type. Then it will be passed by reference and any changes made will reflect back to source. Assuming the databinding process does not create a copy.

Xamarin.Forms Bindable Properties, For more information, see Walkthrough: My first WPF desktop application. and a system that can coerce property values based on potentially runtime information. property metadata, rather than overriding the actual implementation of A dependency property can reference a value through data binding. Data Binding Library gains more and more popularity in production of Android applications as it amplifies the advantages of the MVVM architecture. It allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically.

APL Data-Binding Evaluation, Acting as a valid target property for data binding. The bindable property should be set to the returned value of one of the BindableProperty. For more information, see Coerce value callbacks. Validation callbacks are provided with a value, and should return true if the value is valid for the property,  The value binding links the associated DOM element’s value with a property on your view model. This is typically useful with form elements such as <input>, <select> and <textarea>. When the user edits the value in the associated form control, it updates the value on your view model.

Type awareness and reflection for @bindable and @observable , The data-binding context is a JSON dictionary of key-value pairs, where each value can be a does not advance when the document is "frozen" or hidden from the user's view. True if the OpenURL command is enabled, false otherwise. APL supports type coercion of arrays, implicit array-ification, and interpolation of  E.g. Say you have Textbox control that is bound to a column of a DataTable. Consider that some values in the DataTable are DBNull.Value. In this case, if you would like DBNull.Value to be displayed by the TextBox as say, “ (null)” then you would achieve this by setting NullValue property of the binding to “ (null)”.

Python in a Nutshell, RFC The following is a summary of how I'd like to see the @bindable and @​observable evolve. Specifically, it covers: The need for type awareness and coercion. I'm not suggesting any changes to how the actual value is This can be worked around by writing e.g value.bind="2" instead, but that's  Databinding gives “System.Data.DataRowView” instead of actual values in window form See more: C#3.0. C#. how to bind a column of database to list box control

Comments
  • Seems binding does not support concering val. Have you tried diff mode in TextBox?
  • Interesting, so this is expected behavior. I suppose my next step is to figure out how to supply a bindable ActualValue property that reflects what's actually displayed in the NumericUpDown. Are you aware of a better way than just re-evaluation the coercion in a property changed handler and setting ActualValue there?
  • New question for an old answer :). I have this very issue, but "GetBindingExpression" returns null. I'm trying to coerce when the value is bound! It works when the value is set by the user. So there must be some context issue (not fully loaded or whatever)? Any pointers?
  • If you try to do Value = x at some point then it will clear the binding. Use SetCurrentValue instead.
  • Doesn't it get boxed if it's returned as Object from the coercion method?