views:

566

answers:

3

I'm just getting started with the MVVM pattern in WPF and I decided that the most elegant way to structure my code was injecting the view-model in to the view's constructor.

This is all well and good, but ReSharper gives a warning in the XAML that my view doesn't have a default constructor. I'm assuming that this is so that I can construct my view in XAML if required, but that's only a guess.

What am I giving up by requiring my view to take a view-model in the constructor?

Edit: My view constructor looks like this:

public ExampleView(ExampleViewModel viewModel)
{
    if (viewModel == null) throw new ArgumentNullException("viewModel");
    DataContext = viewModel;
}

Answer: I settled on the following set up, where the DesignTime namespace contains mocked up versions of the ViewModel for testing and design time support.

ExampleView.xaml.cs

public ExampleView()
{
    InitializeComponent();
}

public ExampleView(IExampleViewModel viewModel)
    : this()
{
    DataContext = viewModel;
}

ExampleView.xaml

<UserControl
    x:Class="Wpf.Examples.ExampleView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:DesignTime="clr-namespace:Wpf.Examples.DesignTime">

    <UserControl.DataContext>
        <DesignTime:ExampleViewModel/>
    </UserControl.DataContext>

</UserControl>
A: 

Assuming that you don't need designer support then I see no reasons.

Preet Sangha
A: 

To keep designer support you need a default constructor. When you define your own constructor you basically loose the autogenerated default constructor. Just create an explicit default constructor and you should be fine.

Peter Lillevold
+6  A: 

As you correctly recognized, requiring a non-default constructor will deny you using that control from XAML. That also means no more design-support and your designers will probably hate you. Finally you break all sorts of nice data binding scenarios. Like using the control as an ItemTemplate.

As a remedy for the missing design support, I would suggest implementing a default constructor which creates a mocked view-model which doesn't need any infrastructure. That way you can support design mode very elegantly and putting the view in a XAML file (e.g. for testing) will do something sensible.

As a remedy for the missing data binding support, you should ponder whether it might be better to consume the view model via the DataContext of your WPF control. This is common in WPF and---as far as I can tell---the intended way to pass the model to the view in WPF.

David Schmitt
I'm setting the DataContext in the constructor anyway, is there a better pattern for this?
Jacob Stanley
Use a Factory? Set the DataContext manually? Create an empty default constructor?
David Schmitt