views:

765

answers:

2

This is what I'm trying to do:

  • I'm writing a UserControl that I want to be consumed by other developers.
  • I want end users to be able to use my control using Dependency Properties.

    <lib:ControlView ControlsText={Binding Path=UsersOwnViewModelText} />

  • I'm using the MVVM pattern.

  • I'm binding my ViewModels to their View's using <DataTemplates>.

    <DataTemplate DataType="{x:Type local:ControlViewModel}">
    <local:ControlView />
    </DataTemplate>

So I have two questions:

  1. Am I right in thinking that if a UserControl is being consumed in XAML then the UserControl must set the ViewModel as its DataContext when the control's Loaded event fires instead of using the <DataTemplate> method?

  2. How do I allow users to data bind to my control's dependency properties while still being data bound to my ViewModel?

+2  A: 

You should separate the two use cases:

  1. The (user) control that will be consumed by other developers.
  2. The user control that will be consumed by your application.

Importantly, the latter depends on the former - not vice versa.

Use case 1 would use dependency properties, template bindings, all the things that go into making a regular WPF control:

MyControl.cs:

public class MyControl : Control
{
    // dependency properties and other logic
}

Generic.xaml:

<ControlTemplate Type="local:MyControl">
    <!-- define the default look in here, using template bindings to bind to your d-props -->
</ControlTemplate>

You would then define use case 2 as:

MyViewModel.cs:

public class MyViewModel : ViewModel
{
    // properties and business logic
}

MyView.xaml:

<UserControl ...>
    <local:MyControl SomeProperty="{Binding SomePropertyOnViewModel}" .../>
</UserControl>

Best of both worlds with a clean separation. Other developers depend only on the control, which could (and probably should) be in a completely different assembly than your view model and view.

HTH,
Kent

Kent Boogaart
Thanks for the reply. I'm creating a composite control, think of cascading combo boxes. It seams a little heavy weight to create a control this way for my needs. Thanks for the reply though, as it was still useful to know.
Jon Mitchell
+1  A: 

First off, I don't think MVVM is a good choice if you are developing a UserControl that will be consumed by others. A lookless control is what you really should be developing. Jeremiah Morrill has a blog post about this subject.

With that said, you can set the datacontext with XAML if you have a default public constructor.

Inside ControlView.xaml put:

<UserControl.DataContext>
    <local:ControlViewModel />
</UserControl.DataContext>
Bryce Kahle
It does look like MVVM isn't ideal for creating user controls. So with that mental hurdle out the way I was able to sort my issue. I had to set the DataContext of the child controls in my UserControl to be the UserControl itself, which means that a consuming control can provide the DataContext for my UserControl and hence bind to my DependencyProperties. (I think that's right...) Anyway, it works so I'm happy!!
Jon Mitchell