views:

1041

answers:

1

WPF XAML, I have a custom control I have written that wraps lookups. In typical government fashion, they have a lookup table for all possible lookups. My custom control will throw a popup overlay asking them to select from the items in the list. My problems relate specifically to databinding from my calling form to my control property to my underlying control VM.

I'm calling the control like this:

<Controls:LookupSelector SelectedLookupValueId="{Binding Path=DataContext.SelectedHarvestMethod, ElementName=SurveyFormWindow, Mode=TwoWay}" />

(other spam was removed) In this case, the explicit DataContext is required because the actual datacontext of the control is its own view model. SelectedHarvestMethod is a property on the form ViewModel.

It works in "New Form" mode where the control is responsible for setting its own value (the control includes a button that when you click it, gives you a popup, and you select which value of lookup data you want). That works fine as I said, it even binds back to the 'SelectedHarvestMethod' in the code above. I can use this fine and be confident that my ViewModel always has the selected id assigned to that property.

But now I am doing the "Edit Existing Form" mode where I'm loading data back from database and setting the properties in the view model. So I set the 'SelectedHarvestMethod' and that code works fine (breakpoint hit in setter) but the resulting setter on 'SelectedLookupValueId' is not called - the value never goes through.

'SelectedLookupValueId' is a DP on the control's view model:

public static readonly DependencyProperty SelectedLookupValueIdProperty =

     DependencyProperty.Register("SelectedLookupValueId", typeof(int), typeof(LookupSelector), new UIPropertyMetadata(0));

    public int SelectedLookupValueId
    {

         get { return (int) GetValue(SelectedLookupValueIdProperty); }

         set { SetValue(SelectedLookupValueIdProperty, value); ViewModel.SetPreSelectedLookupValueId(value); }

    }

There's no errors in the output window or event log or written on the bottom of my shoe. Debug converter inserted shows that the integer value is definately assigned. As mentioned in comment, the VM implements INotifyPropertyChanged of course, and is raising the event correctly.

Also, the actual type is 'User Control', not custom control: it has XAML involved.

Why isn't the property setter for my control being called?

+3  A: 

Why isn't the property setter for my control being called?

I confess I haven't read your entire question - it's too long ;) However, are you sure the binding is failing? Know that WPF optimizes dependency property access such that the getter and setters of your CLR wrapper are not invoked. Instead, it invokes DependencyObject.GetValue and DependencyObject.SetValue directly, passing in the appropriate DependencyProperty instance.

Therefore you can't set a breakpoint on your CLR property to determine whether the d-prop is being changed. Instead, specify a change handler in the metadata for the d-prop. Then set a breakpoint in this handler. You can also use tools like Snoop to see this.

Incidentally, this is why your CLR wrapper property should never do more than call GetValue and SetValue. It exists for convenience only and any extra logic you package with the property won't be guaranteed to execute.

HTH, Kent

Kent Boogaart
+1 Even if this isn't the problem in this particular case there's a good chance it will be for someone looking at this question in the future.
Bryan Anderson
+1 This was the issue. I hooked into the callback instead. I was able to do so with code similar to that presented in this article:http://blogs.msdn.com/llobo/archive/2007/03/05/listening-to-dependencyproperty-changes.aspx
DarkwingDuck
Side note: If the name string you pass to DependencyProperty.Register is different from the CLR property names, the DP system _will_ call the GetValue and SetValue (and it will otherwise still behave as a DP). The custom callback is a much better design, but this hack is useful if you want to create attached collection properties.
Robert Fraser