views:

253

answers:

3

I have come accross two ways of initializing Views and ViewModels in WPF CAL MVVM.

1 - Seems to be more popular. Requires you to resolve the ViewModel to automatically resolve the View. The ViewModel contains information about the View.

    public interface IView
    {
        void SetModel(IViewModel model);
    }

    public interface IViewModel
    {
        IView View { get; }
    }

    public class View
    {
        public void SetModel(IViewModel model)
        {
            this.DataContext = model;
        }
    }

    public class ViewModel
    {
        private IView view;

        public ViewModel(IView view)
        {
            this.view = view;
        }

        public IView View { return this.view; }
    }

2 - Seems a lot cleaner and removes the View from the ViewModel. Requires you to resolve the View to automatically resolve the ViewModel. Injects objects into the view (Not sure if this is good or not).

    public interface IView
    {
    }

    public interface IViewModel
    {
    }

    public class View
    {
        private IViewModel model;

        public View(IUnityContainer unityContainer)
        {
            this.model = unityContainer.Resolve<IViewModel>();
            this.DataContext = this.model;
        }
    }

    public class ViewModel
    {
    }

What is the accepted method of initializing the views and models and what are the advantages and disadvantages of each method. Should you be injecting objects into your view?

+1  A: 

Option 1 looks about right, give the view a reference to the viewmodel.

Having viewmodels with a reference back to the view seems a bit fishy to me though. That looks more like a model-view-presenter type architecture. If you've got viewmodels that interact heavilly with the view and need a reference to the view for that you might be better off splitting the viewmodel in a viewmodel used purely for databinding and a presenter that does more complex interaction.

Option 2 doesn't look right at all. Passing a reference to the ioc container into classes is a big code smell in my book. Calls to an IoC container should be minimized. In most of my applications I only call into the container at the start of the program to wire stuff up. More dynamic object creation is usually done with factory classes.

Mendelt
The View property in option 1 has been found by me in various examples but I agree that it should not be there.
anon
+1  A: 

I prefer to define the view model in XAML and provide a read-only property for typed access:

<UserControl ...>
    <UserControl.DataContext>
        <local:MyViewModel/>
    </UserControl.DataContext>

    ...

</UserControl>

public partial class MyView : UserControl, IMyView
{
    public MyViewModel ViewModel
    {
        get { return this.DataContext as MyViewModel; }
    }

    ...
}
Rafa Castaneda
+1 for the read only property
Simon_Weaver
+1  A: 

They are both valid, but #1 tends to be more testable (it at least makes your tests more concise). The advantage to #2 is that it tends to be more explicit and makes maintenance a little more clear, especially when you have a lot of turnover, that kind of thing. Takes less explaining (though this is not a reason to adopt it, it's just a truism).

The difference is that #1 is called Dependency Injection and #2 is called Service Location. They are often confused because they both generally utilize some sort of IoC container (although this doesn't have to be the case).

It's a matter of preference in the end, but as I said I think you will find #1 a lot easier to test... you won't have to involve the IUnityContainer interface in your testing / mocking.

Anderson Imes