0

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?

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 from me. I didn't see that he setup his dependency property all wrong.
This works, thank you. Is dependency properties the correct way of binding a view-field (FooView.Value) to a model property (FooViewModel.Value) before the data context has been set, or is there a simpler way to do this? All I want to achieve is to keep FooView.Value in sync with any future viewmodel/data context.
I can't think of many other ways to bind a property. The target of a WPF binding has to be a dependency property.
1

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); } 

4 Comments

I've also tried changing the FooView constructor to react to DataContextChanged and setting up a binding using your code (setting Source to the new model provided by the DependencyPropertyChangedEventArgs), but this does not seem to make any difference.
@larsm I am reading through your code now, but it seems wrong. Your DependencyProperty seems to be set up wrong. What are you actually trying to achieve?
I'm trying to make FooView.Value to be set whenever I set FooViewModel.Value.
@larsm See Clemens's answere.
0

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);| 

2 Comments

Yes, but setting Title was only a way to see if the Value-setter was called, not something I actually wanted to achieve.
you can achive by simple putting value's propertyvaluechangedcallback

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.