Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Property - Updating the source

I am driving crazy with a custom Dependency Property. I already checked loads of threads here, but haven't found any solution yet. What I want to do is to replace the value of the Property if the source provides a specific value (null for the given example). No matter what I try, the property value within the source remains null and is never updated.

Here is my Custom Control:

public class TextBoxEx : TextBox
{
    public TextBoxEx()
    {
        TrueValue = 0;
        this.TextChanged += (s, e) =>
        {
            TrueValue = Text.Length;
            SetCurrentValue(MyPropertyProperty, TrueValue);
            var x = BindingOperations.GetBindingExpression(this, MyPropertyProperty);
            if (x != null)
            {
                x.UpdateSource();
            }
        };
    }

    public int? TrueValue { get; set; }

    public int? MyProperty
    {
        get { return (int?)GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }

    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int?), typeof(TextBoxEx), new PropertyMetadata(null, PropertyChangedCallback));

    private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue == null)
        {
            d.SetCurrentValue(MyPropertyProperty, (d as TextBoxEx).TrueValue);
        }
    }
}

Here is the DataContext i am Binding:

public class VM : INotifyPropertyChanged
{
    private int? _Bar = null;

    public int? Bar
    {
        get { return _Bar; }
        set
        {
            _Bar = value;
            OnPropertyChanged("Bar");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

My Binding looks like this:

<local:TextBoxEx MyProperty="{Binding Bar, UpdateSourceTrigger=PropertyChanged}"/>

Remember: I need a TwoWay binding, so OneWayToSource does not work for me.

Any idea what I am not getting in here?

like image 964
Jaster Avatar asked Sep 01 '11 08:09

Jaster


1 Answers

You just need to set the binding to two-way and it will work. But as that should be the default you can register the property accordingly using the following metadata:

... new FrameworkPropertyMetadata(null,
                                  FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                  PropertyChangedCallback)

Getting the expression in the TextChanged handler and updating source manually is not required so i would remove that code.


If you do not explicitly set a mode on a binding the default will be used, from the documentation:

Default: Uses the default Mode value of the binding target. The default value varies for each dependency property. In general, user-editable control properties, such as those of text boxes and check boxes, default to two-way bindings, whereas most other properties default to one-way bindings. A programmatic way to determine whether a dependency property binds one-way or two-way by default is to get the property metadata of the property using GetMetadata and then check the Boolean value of the BindsTwoWayByDefault property.

like image 161
H.B. Avatar answered Sep 23 '22 01:09

H.B.