larsmoa
larsmoa

Reputation: 12932

Binding a property in code

I'm trying to set up a property binding (WPF) in code. The code compiles fine, but the property I bind is never set. Below follows a minimal example:

The view-model:

public class FooViewModel: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _value;
    public string Value 
    { 
        get { return _value; }
        set
        {
            _value = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Value"));
        }
    }
}

The view:

public class FooView: Window
{
    public string Value
    {
        get { return Title; }
        set
        {
            // Breakpoint here never hits!
            Title = value;
        }
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(FooView));

    public FooView()
    {
        Binding valueBinding = new Binding("Value");
        valueBinding.Mode = BindingMode.OneWay;
        SetBinding(ValueProperty, valueBinding);
    }
}

The "main()":

        FooView view = new FooView();
        FooViewModel model = new FooViewModel();
        view.DataContext = model;
        view.Show();
        model.Value = "ABC";

I expected the FooView.Value-setter to be invoked when model.Value is set. I've also tried explicitly setting the Binding.Source property to the model. How should the binding be set up?

Upvotes: 0

Views: 146

Answers (3)

JSJ
JSJ

Reputation: 5691

if i am not wrong you are about to set the title property of your fooview window from code behind. if so then you can use thexe binding lines under your fooview constructor

 Binding valueBinding = new Binding("Value");
valueBinding.Mode = BindingMode.TwoWay;
SetBinding(TitleProperty, valueBinding);|

Upvotes: 0

Willem
Willem

Reputation: 9476

I think you are missing the Source property:

Binding myBinding = new Binding("Value");
myBinding.Source = TheSourceOfTheProprty;
myBinding.Mode = BindingMode.OneWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
myBinding.IsAsync = false;

BindingOperations.SetBinding(YourControl, YourControl.Property, myBinding);

After fixing your Dependency Property like Clemens explained, then you just need to setup your binding and you will good to go.

So your binding with look like this:

FooViewModel model = new FooViewModel();

FooView view = new FooView(model);
view.DataContext = model;
view.Show();
model.Value = "ABC";


public FooView(FooViewModel model)
{
    Binding myBinding = new Binding("Value");
    myBinding.Source = model;
    myBinding.Mode = BindingMode.OneWay;
    myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;

    BindingOperations.SetBinding(this, this.Value, myBinding);
}

Upvotes: 1

Clemens
Clemens

Reputation: 128061

The problem here is that the Value property is completely unrelated to the ValueProperty dependency property.

The CLR wrapper for a dependency property needs to call the DependencyObject's GetValue and SetValue methods like below:

public string Value
{
    get { return (string)GetValue(ValueProperty); }
    set { SetValue(ValueProperty, value); }
}

In order to get notified about property changes, you would have to register a PropertyChangedCallback with the PropertyMetadata:

public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register(
        "Value", typeof(string), typeof(FooView),
        new PropertyMetadata(ValuePropertyChanged));

private static ValuePropertyChanged(DependencyObject obj,
    DependencyPropertyChangedEventArgs e)
{
    // obj is your FooView instance
    // get new property value from e.NewValue
}

Get more information in Custom Dependency Properties.

Upvotes: 3

Related Questions