C# – Using MVVM in large applications – sharing viewmodels, models, states etc

cmvvmnet

I was wondering if any of you guys know some good tutorial explaining MVVM for large applications. Every tutorial on MVVM i found are just basics explained (how to implement model, viewmodel and view), but I'm curious on techniques and patterns when it comes to passing data between application pages, where to init viewmodels, where to store common application data (shared between multiple viewmodels) etc.

I prefer pure c#/XAML solutions without any MVVM frameworks (MVVMLight etc).

Best Answer

techniques and patterns when it comes to passing data between application pages

If the data passing is event-driven (i.e: you want to notify when you receive data pushed from a server), use weak events. Prism's EventAggregator is one of many implementations.

If the data passing is constant, let the DataContext flow down the XAML tree and simply use binding.
That means if you have a "master" UserControl that uses other, more specific, UserControls, don't set their DataContext, they will inherit the master's and all is well.
If you want to separate functionality, use composition in the master's viewmodel.

where to init viewmodels

Purists will tell you to instantiate them directly in XAML. I almost never do that.
First of all, ViewModels usually need services, and they're passed as constructor parameters, or injected via MEF in the constructor... etc. So you can't have a parameterless constructor, or it's harder.

Now, we can do hard stuff, but what's the gain? It's perfectly fine to let the code-behind of the view retrieve the ViewModel, or get it injected in its constructor.

where to store common application data (shared between multiple viewmodels)

If the data is global: use static classes/properties,
in XAML you can access them via {x:Static my:StaticClass.StaticProperty}, if you want to reach a nested class/enum, use + instead of .

If the data is only shared between several ViewModels but not all, use inheritance/composition on the viewmodels, along with a controller pattern.

Other tips gathered from experience:

  • Only bind strictly what you need: don't bind to an entire object when you just need a string in there.

  • If you're binding the same thing again and again, don't hesitate to make custom markup by inheriting from Binding/MultiBinding. It's DRY 101, but most people just copy/paste Bindings for some reason.

Example:

public class VisibilityBinding : MultiBinding, IMultiValueConverter
{
   public VisibilityBinding()
   {
      var isSomething = new Binding("IsSomething");
      isSomething.ElementName = myUsrCtrl;
      this.Bindings.Add(isSomething);

      //Add more bindings

      this.Converter = this;
    }

    //Implement IMultiValueConverter to compute a System.Visibility from the bound values.
}

And in XAML:

 <TextBox Visibility={customMrkup:VisibilityBinding} />
  • Avoid at all cost any data duplication, all the way down to the DAL. It becomes complex really fast to synchronize fields that could just be deduced through an I(Multi)ValueConverter.
    Example: You have an audio file. It has a start time, an end time, and a duration. Get rid of any of these 3 properties, the third can be deduced.

If I think of any more tips I'll come back and add them.

Hope this helps!

Related Topic