Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM + UserControl + Dependency Property

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.

like image 465
Tom L. Avatar asked Mar 02 '13 15:03

Tom L.


2 Answers

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}"/>
like image 128
Clemens Avatar answered Oct 28 '22 17:10

Clemens


Alright, after hours of googling it appears that the "correct" approach to this is not to do it at all. The general approach is to keep the data in your MainViewModel and not use an additional ViewModel for the UserControl (which I find a little ... well .. not so good). The main problem is that there is no easy mechanism to get the Data from the Dependency Property to the ViewModel.

For printing, I have now gone back to doing it purely in code.

like image 42
Tom L. Avatar answered Oct 28 '22 19:10

Tom L.