11
votes

I am quite new to MVVM pattern so please bear with me. I have seen implemnentations in wpf +mvvm + prism where all the views tend to have an IView as top most interface. Then the views in the respective modules have a view specific interface like IViewA, IViewB etc which implement the IView interface. Even the viewmodel has IViewModel top most interface and the subsequent modules have IViewAViewModel , IViewBViewModel etc that inherit from the IViewmodel. IViewmodel has a reference to Iview and the Iview has a reference to IViewModel.

namespace xxx.xxx.infrastructure
{
public interface IView
{
  IViewModel ViewModel {get;set;}
}

public interface IViewModel 
{
  IView View {get;set;}
}

public abstract class ViewModelBase : IViewModel, INotifyPropertyChanged
{

   public IView View {get;set;}

   public ViewModelBase(IView view)
   {
     View = view;
     View.ViewModel = this;
   }
   //INotifyPropertyChanged left out
 }
}

namespace xxx.xxx.Modules.Customer
{
   public interface ICustomerDetailsView : IView
   {

   }

   public partial Class CustomerDetailsView : UserControl, ICustomerDetailsView 
   {
       public CustomerDetailsView ()
       {
         InitializeComponent();
       }

       //Is this implementation acceptable?The view is supposed to have zero code in       the code behind.....
        public IViewModel ViewModel
        {
          get
          {
            return (ICustomerDetailsViewViewModel)DataContext; 
          }
          set
          {
             DataContext = value;
          }
        }

    }  

    public interface ICustomerDetailsViewViewModel : IViewModel
    {
       string Message {get;set;}
    }

     public class CustomerDetailsViewViewModel : ViewModelBase,       ICustomerDetailsViewViewModel 
    {
      //Will be injected by unity as i have set up mappings in module initilize.
      public CustomerDetailsViewViewModel(ICustomerDetailsView view)
          :base(view)
      {
      }

       public string Message
       {
          //INotifyPropertyChanged left out for brevity
          get;set;
       }
   }

I have a few questions.

1.)Isnt this violation of MVVM as code behind file is supposed to have zero code?

2.)in MVVM view model should not worry the view or its contract?Doesnt the above implementation break it?

3.)I cannot understand what is the use of this implementation. In fact this borders on MVP and lot of code is required.

4.)If this is an acceptable way to implement, do i need to have interfaces for all the views and viewmodels in all of my modules.?

2
I havent worked with WPF much, but I agree on your opinion as a design practice. VM should not have a reference to the View, and I don't see a need for it, unless you are NOT using bidirectional bindings properly. Regarding interfaces everywhere... this is the unfortunate truth of static languages where the contracts need to be in the form of interfaces. Unity should be demanding interfaces for it's DI stuff..Hasith
@Hasith Its actually not the concrete implementation of the view but only an interface of the view. I can argue saying that this still satisfies MVVM because the VM has no idea about the Window/Page that implements IViewHari Subramaniam
Yes, but still the view model needs to know about the contract of the view. Meaning more coupling than with a independent ViewModel. Why do you need that when bidirectional bindings are in place? Imagine when you need multiple views to share the same view model (e.g. tightly related multiple UI components in the same window).. Don't know how it work in WPF, but I have used that as a powerful practice in Javascript MVVM frameworks.Hasith
a "View Model" isn't the model; it's more of a "controller" or "presenter" that decouples the view from the real model. Of course, a real model is optional and in many situations the VM acts as the model...Peter Ritchie
@Hasith: Absolutly agree with you, no needs inject any IView in ViewModel. MVVM based on Presentation Model pattern, so View worries about syncronization state with View(Presentation)Model. ViewModel just need to raise event that it state has been changed and View will sinchronize (via event subscription or binding). If IView injects in ViewModel, it means that ViewModel worries about syncronization states with it View, and looks like MVP Supervising Controller.Vladimir Dorokhov

2 Answers

8
votes

Basically, we need interfaces for injections only. There are 2 ways:

  • Inject ViewModels to Views

It will mean that the ViewModel no longer has any back reference to the View. This means when unit-testing the ViewModel you don't need a mock view. Additionally it makes the code cleaner, in that in the constructor of the View, it simply sets the DataContext to the ViewModel that was injected.

  • Inject Views to ViewModels.

It avoids to keep workflow logic into the Presentation layer. It means that the Application layer keeps responsible for the application workflow. This way the workflow logic is highly coupled with the Views and so it is quite impossible to write unit test for this.

18
votes

first a very nice comment from Rachel regarding viewmodel first:

Remember, with MVVM your ViewModels are your application. The View is just a pretty interface that allows users to interact with your ViewModels.

1) IView is a violation of MVVM for me, but codebehind is of course allowed for ui stuff. viewmodel should just have no reference to the view. see 1st comment from Hasith

2) see my blockquote

3) i'm with you - i never use something like that in my projects

4) pls do MVVM the easy way - no coupling, use di, ioc, commanding, behaviors and for me the most important: viewmodel first:)