Andy
Andy

Reputation: 1080

DependencyProperty on ViewModel of UserControl not updated by Binding

I have a UserControl which is used as the basis for items in an ItemsControl:

Main Page xaml:

<ItemsControl ItemsSource="{Binding Systems, Mode=TwoWay}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <local:ServerGroupControl>
                <local:ServerGroupControl.DataContext>
                    <local:ServerGroupControlViewModel System="{Binding}"/>
                </local:ServerGroupControl.DataContext>
            </local:ServerGroupControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

I am trying to set the 'System' property of each ViewModel (such that it can handle the data for the view), but the property is never set!

Here is the dependancy property declaration in the view model class:

    public static readonly DependencyProperty SystemProperty = DependencyProperty.Register(
        "System",
        typeof(ServerGroup),
        typeof(ServerGroupControlViewModel)
    );

    public ServerGroup System
    {
        get { return (ServerGroup)GetValue(SystemProperty); }
        set { SetValue(SystemProperty, value); }
    }

The property always keeps it's default value. Any ideas on why this setup does not work?

Upvotes: 1

Views: 2321

Answers (2)

brunnerh
brunnerh

Reputation: 184376

So based on your comment i would suspect that the binding does not work because there is no DataContext in the place where you try to bind.

Your VM is not a FrameworkElement so it has no DataContext property, presumably it is not Freezable either (and hence might lack an inheritance context too) so i suspect that this won't work. (ElementName and RelativeSource won't work either then, by the way)

I suggest you approach this differently, also i do not recommend the use of DPs in VMs due to thread-affinity and other problems.


Here's one gem of a work-around:

<DataTemplate>
    <local:ServerGroupControl Name="sgc">
        <local:ServerGroupControl.Resources>
            <local:ServerGroupControlViewModel x:Key="context"
                System="{Binding Parent.DataContext, Source={x:Reference sgc}}" />
        </local:ServerGroupControl.Resources>
        <local:ServerGroupControl.DataContext>
            <StaticResource ResourceKey="context" />
        </local:ServerGroupControl.DataContext>
    </local:ServerGroupControl>
</DataTemplate>

Yeah, please don't do that...

Upvotes: 1

Andrew Shepherd
Andrew Shepherd

Reputation: 45222

When a property is set through databinding, the explicit setter function is not called.

If you really want to intercept the setting action, you can do this via a callback that you set when initializing the Dependency Property.

public static readonly DependencyProperty SystemProperty = DependencyProperty.Register(
        "System",
        typeof(ServerGroup),
        typeof(ServerGroupControlViewModel),
        new PropertyMetadata
        {
            PropertyChangedCallback = SystemPropertyChanged
        }
    );


static void SystemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ServerGroupControlViewModel receiver = (ServerGroupControlViewModel)d;
    ServerGroup newValue = e.NewValue as ServerGroup;

    // Add any appropriate handling logic here.
}

Upvotes: 0

Related Questions