0

I got a binding source not being updated when the targeted DependencyProperty of a custom UserControl changes.

The source is a ViewModel loaded with MEF into the DataContext of my custom UserControl.

My binding looks like this in the root XAML of MyUserControl

// MyUserControl.xaml
<MyUserControlBase x:Class="MyUserControl" MyDependencyProperty="{Binding ViewModelProperty}">

If i use the MyDependencyProperty with a FrameworkPropertyMetadata and use the callback function when the property changes i can do the following which works fine

// MyUserControlBase.cs
private static void MyDependencyProperty_Changed(DependencyObject depObj, DependencyPropertyChangedEventArgs args)
{
    var filter = (UserControl )depObj;
    var vm = (ViewModel)filter.DataContext;
    vm.ViewModelProperty= (VMPropType)args.NewValue;
}

Registration of the DependencyProperty in MyUserControlBase which inherit UserControl.

// MyUserControlBase.cs
public static readonly DependencyProperty MyDependencyPropertyProperty = DependencyProperty.Register("MyDependencyProperty",
            typeof(VMPropType),
            typeof(MyUserControlBase),
            new FrameworkPropertyMetadata(null, MyDependencyProperty_Changed));

But why can't i get the simple two way binding to work when done in the XAML?

Output window show no binding failurs. I can see the ViewModel.ViewModelProperty getter is being called. Just not the setter once MyDependencyProperty changes.

It don't appear to be a problem with the ordering of events. The ViewModel is created long before DependencyProperty is changed for the first time.

I've also looked at Setting up binding to a custom DependencyProperty inside a WPF user control But his problem seems slightly different since i actualy inherit from my own Base class which holds the DependencyProperty.

Thank you for any help.

Edit: with link to example solution. Solution zip here

Sorry for the scary looking link, I don't know alot of quick fileshareing sites. If its bad post comment and I will remove it asap, but it seems ok.

Community
  • 1
  • 1
CodeMonkey
  • 3,418
  • 4
  • 30
  • 53

2 Answers2

0

Answer updated / irrelevant info deleted

After looking at the code in your sample I saw what the problem is. You have this "selector" control. In the BindDependencies method you set a binding on the MyControlBase.MyDependencyProperty. But at the same time you also bind this property to your control's datacontext (in MyUserControl.xaml). Effectively this means that in the BindDependencies method you are overwriting the binding to your viewmodel thus it is not active after that method - you can see this yourself by breaking into before and after the SetBinding call and calling BindingOperations.GetBindingExpression(control, MyUserControlBase.MyPropertyDependencyProperty) - the bindings are different. This is why your code does not work. I guess you will have to find another way of transferring the value there :)

Some additional info

In WPF a property can be a target of only one binding. This is actually very logical - if a property is bound to two sources - which one should it use? The fact that the binding is marked as OneWayToSource does not really matter in this situation as it still counts as a binding that targets the control's property.

One way you can investigate and see if it works for you is the MultiBinding - it does allow to bind the control's property to several sources by implementing your own IMultiValueConverter. You can find more info on this on MSDN in the link provided.

Jefim
  • 3,017
  • 4
  • 32
  • 50
0

Do you expose the ViewModelProperty as a regular property..

Usually you do the following....

public static readonly DependencyProperty ViewModelPropertyProperty = DependencyProperty.Register("ViewModelProperty", 
            typeof(VMPropType), 
            typeof(MyUserControlBase), 
            new FrameworkPropertyMetadata(null, ViewModelProperty_Changed)); 

public VMPropType ViewModelProperty {
    get { return (VMPropType)GetValue(ViewModelPropertyProperty); }
    set { SetValue(ViewModelPropertyProperty,value); }
}

EDIT -- After comment.

When are you checking that the property has changed? By default WPF bindings only update the values when they lose focus, you change change the UpdateSourceTrigger property of the binding to alter this behaviour.

Bob Vale
  • 18,094
  • 1
  • 42
  • 49
  • In MyUserControlBase_Changed method which is the callback from the DependencyProperty's Register method. The DependencyPropertyChangedEventArgs.NewValue appears correct. It just don't update my XAML binding source. I have tried with UpdateSourceTrigger=PropertyChanged. – CodeMonkey Jul 23 '12 at 14:39
  • Can you add a check in the actual setter for ViewModelProperty. It's possible that you are checking too early and the change has not cascaded through yet. – Bob Vale Jul 23 '12 at 14:42
  • I've done that, but it only gets hit when i do 'new MyUserControl()" and MEF creates the ViewModel. I get a two get's which return null and a set which assigns null. After that i see a proc on MyUserControlBase.MyDependencyProperty_Changed where the args contain the correct value. But nothing in my ViewModel changes. – CodeMonkey Jul 23 '12 at 15:25