Wpf – MVVM + UserControl + Dependency Property

dependency-propertiesmvvmuser-controlswpf

Alright, this is somewhat related to this question: WPF Printing multiple pages from a single View Model

I tried to follow the advice given there but now I am stuck.

My application uses a MainView.xaml and the appropriate MainViewViewModel.cs, I am using MVVM Light in the background.

Now – according to the post – it seems I have to do the following:

  • Create a user control
  • Expose some properties from the user control
  • Make sure the view model shows these properties

The idea is clear but I am stuck when trying to notify each other.

My user control (UcTest.xaml) exposes a Dependency Property:

public string SpecialText
{
    get { return (string)GetValue(SpecialTextProperty); }
    set
    {
        SetValue(SpecialTextProperty, value);

    }
}

// Using a DependencyProperty as the backing store for SpecialText.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty SpecialTextProperty =
    DependencyProperty.Register("SpecialText", typeof(string), typeof(UcTest), new PropertyMetadata(new PropertyChangedCallback(SpecialTextChangedPropertyCallback)));

private static void SpecialTextChangedPropertyCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    // Do something
    Debug.WriteLine("Ffgdgf");
}

Alright, so I do now have a user control which has some dependency properties. Yet, these properties are completely separated from my ViewModel properties (those are the ones which shall be displayed).

So basically I have two possibilities:

  • How can I now tell my ViewModel for the UserControl that some properties have changed?
  • Is there a possibility to forget about the dependency properties and access the view model directly?

Additional info #1:
I have uploaded a (simple) example of what I am trying to do here: Example Project. I would like to change the value of the label in UserControl1 (via the binding property in the ViewModel for UserControl1) from my MainViewViewModel.

Best Answer

You would usually bind the UserControl's property to the ViewModel property. A two-way binding would work in both directions, from ViewModel to View and vice versa.

<Window x:Class="TestApplication.MainWindow" ...>
    <Window.DataContext>
        <local:MyViewModel/>
    </Window.DataContext>
    <Grid>
        <local:UcTest SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>
    </Grid>
</Window>

To directly access the ViewModel object in the above example, you could simply cast the UserControl's DataContext property to the ViewModel type. The DataContext is inherited from the MainWindow.

var viewModel = DataContext as MyViewModel;
var property = viewModel.MyViewModelProperty;

You could of course also directly assign a specialized ViewModel instance to the UserControl's DataContext:

<local:UcTest SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>
    <local:UcTest.DataContext>
        <local:UserControlViewModel/>
    </local:UcTest.DataContext>
</local:UcTest>

or you may create the ViewModel instance as a resource in a resource dictionary and assign the DataContext like this

<local:UcTest DataContext="{StaticResource MyUserControlViewModel}"
              SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>
Related Topic