Browse by Tags

All Tags » model-view-viewmodel   (RSS)

Even if you don't use Jounce, this post will help you better understand how to create non-shared views and view models with the Managed Extensibility Framework (MEF). The architecture I prefer in Silverlight is to keep a shared view and view model where possible. If only one instance of the view is visible at a time, the view model can be manipulated to provide the correct bindings and information when different data is selected for that view. Keeping a single view avoids issues with waiting for multiple views in garbage collection or keeping track of multiple views that might not unhook from the visual tree correctly.

There are several cases where this is not plausible. In a master/detail scenario with dockable views, you may end up with multiple "detail" views on the screen. Each view requires a separate copy and possibly a separate view model as well.

Lazy Shared Views and View Models

In MEF, the Lazy<T,TMetadata> syntax is used to import multiple implementations of a contract and associated metadata. The pattern allows you to inspect the metadata before creating the object instances, so you have full control over what is happening. Jounce uses this feature to bind views and view models by inspecting the metadata and using that to examine "routes" created by the user (a route simply asserts that view "X" requires view model "Y").

The view model import looks like this:

[ImportMany(AllowRecomposition = true)]
public Lazy<IViewModel, IExportAsViewModelMetadata>[] ViewModels { get; set; }

The array can be queried with LINQ. In Jounce, the view model metadata simply provides a user-defined tag for the view model so it can be referenced without knowing the type (this is useful, for example, when the view model must be referenced before the XAP that contains it has been loaded). Here is the metadata contract:

public interface IExportAsViewModelMetadata
{
    string ViewModelType { get; }
}

Here is a simple query to get the associated information for the view model. What's important to note is that part of this information is a Lazy<T> property for the view model. When the value property is accessed, the view model is created, but any subsequent references will use the same copy, or a "shared" view model:

var vmInfo = (from vm in ViewModels
                where vm.Metadata.ViewModelType.Equals(viewModelType)
                select vm).FirstOrDefault();

Using the Export Factory

To get a fresh copy, instead of using the lifetime management attributes that MEF provides, I chose to go with the ExportFactory. Unlike a Lazy import, the export factory does not provide a copy of the target object. Instead, it provides the means of creating a new copy. In other words, you are provided with an actual factory to generate new copies. The convention for this is very similar to the lazy version:

[ImportMany(AllowRecomposition = true)]
public List<ExportFactory<IViewModel, IExportAsViewModelMetadata>> ViewModelFactory { get; set; }

Notice that again metadata exists, so you can inspect the factory to make sure it is the right factory before asking it to generate a new object. Now it is a simple matter to query for the right view model and then ask the export factory to generate a new copy:

public IViewModel GetNonSharedViewModel(string viewModelType)
{
    return (from factory in ViewModelFactory
            where factory.Metadata.ViewModelType.Equals(viewModelType)
            select factory.CreateExport().Value).FirstOrDefault();
}

The Ties that Bind

Now you are able to generate a view and a view model on the fly. Jounce adds helper methods to view models to help synchronize with the view. For example, InitializeViewModel is called the first time the view model is bound to the view, and ActivateView is called when a view is loaded that is bound to the view model. There is also a binding for the visual state manager so that the view model can transition states without being aware of the view.

In order to bind property, Jounce provides a simple mechanism for generating a new copy of a view that allows you to pass in the data context:

UserControl GetNonSharedView(string viewTag, object dataContext);

If you have simple views, this can take a model or other class that is not a view model and will still bind it to the data context for you. However, if the bound object is a Jounce view model, the binding will add some additional calls and hooks to ensure that visual states and other bindings are updated as needed. This is what the view creation method looks like:

public UserControl GetNonSharedView(string viewTag, object dataContext)
{
    var view = (from factory in ViewFactory
                where factory.Metadata.ExportedViewType.Equals(viewTag)
                select factory.CreateExport().Value).FirstOrDefault();

    if (view == null)
    {
        return null;
    }

    _BindViewModel(view, dataContext);
                
    var baseViewModel = dataContext as BaseViewModel;
    if (baseViewModel != null)
    {
        baseViewModel.RegisterVisualState(viewTag,
                (state, transitions) => JounceHelper.ExecuteOnUI(
                  () => VisualStateManager.GoToState(view, state, transitions)));
        baseViewModel.RegisteredViews.Add(viewTag);
        baseViewModel.Initialize();
        RoutedEventHandler loaded = null;
        loaded = (o, e) =>
                        {
                            ((UserControl) o).Loaded -= loaded;
                            baseViewModel.Activate(viewTag, new Dictionary<string, object>());
                        };
        view.Loaded += loaded;
    }
    return view;
}

Notice the use of the variable to allow unbinding the lambda expression after the first loaded event is fired (the load event is triggered every time the control is placed in the visual tree, but the bindings only need to be updated once).

DataTemplate Selectors

The final step for Jounce was to create a special value converter for spinning views. This is similar to the concept I wrote about in Data Template Selector using the Managed Extensibility Framework. Only in this case, the converter will do one of two things: if passed a Jounce view model, it will automatically find the view the view model is associated with, generate a new copy of the view, and bind it, or if passed a parameter, it will create a view with the tag provided in the parameter.

The Jounce quickstart (available by grabbing the latest Jounce source download) contains an example of this. The target model is a contact class:

public class Contact
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
}

The view model for the model simply passes through to the underlying properties. In a full implementation, it would save the orignal model for roll back and have other options such as commands to manipulate the data:

[ExportAsViewModel("ContactVM")]
public partial class ContactViewModel : BaseViewModel
{
    public ContactViewModel()
    {
        if (DesignerProperties.IsInDesignTool)
        {
            SetDesignerData();
        }
    }

    public Contact SourceContact { get; set; }
        
    public string FirstName
    {
        get { return SourceContact.FirstName; }
        set
        {
            SourceContact.FirstName = value;
            RaisePropertyChanged(()=>FirstName);
        }
    }

    public string LastName
    {
        get { return SourceContact.LastName; }
        set
        {
            SourceContact.LastName = value;
            RaisePropertyChanged(()=>LastName);
        }
    }

    public string Address
    {
        get { return SourceContact.Address; }
        set
        {
            SourceContact.Address = value;
            RaisePropertyChanged(()=>Address);
        }
    }

    public string City
    {
        get { return SourceContact.City; }
        set
        {
            SourceContact.City = value;
            RaisePropertyChanged(()=>City);
        }
    }

    public string State
    {
        get { return SourceContact.State; }
        set
        {
            SourceContact.State = value;
            RaisePropertyChanged(()=>State);
        }
    }
}

The view simply shows the last name, first name in bold and then the address on the second line:

<Grid x:Name="LayoutRoot" Background="White" d:DataContext="{d:DesignInstance vm:ContactViewModel, IsDesignTimeCreatable=True}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" Margin="5">
        <TextBlock FontWeight="Bold" Text="{Binding LastName}"/>
        <TextBlock FontWeight="Bold" Text=", "/>
        <TextBlock FontWeight="Bold" Text="{Binding FirstName}"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal" Grid.Row="1" Margin="5">
        <TextBlock Text="{Binding Address}"/>
        <TextBlock Text=" "/>
        <TextBlock Text="{Binding City}"/>
        <TextBlock Text=", "/>
        <TextBlock Text="{Binding State}"/>
    </StackPanel>
</Grid>

Here is the view with sample data in the designer:

The view itself is exported in the code-behind, as well as a binding mapping it to the corresponding view model:

[ExportAsView("ContactView")]
public partial class ContactView
{
    public ContactView()
    {
        InitializeComponent();
    }

    [Export]
    public ViewModelRoute Binding
    {
        get { return ViewModelRoute.Create("ContactVM", "ContactView"); }
    }
}

The main view model starts out by providing a list of contacts (this one generates sample data for the sake of the demo):

[ExportAsViewModel("MainVM")]
public class MainViewModel : BaseViewModel
{
    private readonly List<Contact> _sampleData = new List<Contact>
                                            {
                                                new Contact
                                                    {
                                                        FirstName = "Jeremy",
                                                        LastName = "Likness",
                                                        Address = "1212 Hollywood Blvd",
                                                        City = "Hollywood",
                                                        State = "California"
                                                    },
                                                new Contact
                                                    {
                                                        FirstName = "John",
                                                        LastName = "Doe",
                                                        Address = "12 Driving Parkway",
                                                        City = "St. Petersburg",
                                                        State = "Florida"
                                                    },
                                                new Contact
                                                    {
                                                        FirstName = "Jane",
                                                        LastName = "Doe",
                                                        Address = "1414 Disk Drive",
                                                        City = "Lead",
                                                        State = "South Dakota"
                                                    },
                                                new Contact
                                                    {
                                                        FirstName = "Sam",
                                                        LastName = "Iam",
                                                        Address = "12 Many Terrace",
                                                        City = "Figment",
                                                        State = "Imagination"
                                                    },

                                            };

    public MainViewModel()
    {
        Contacts = new ObservableCollection<Contact>(_sampleData);
    }

    public ObservableCollection<Contact> Contacts { get; private set; }
}

The problem is that our view requires a view model (it might handle edits or deletes in the future, so the model itself isn't enough). No problem! First, create a set of extension methods: one to pass the contact into a view model, and another to handle a list of contacts that will return a list of contact view models:

public static ContactViewModel ToViewModel(this Contact contact, IViewModelRouter router)
{
    var vm = router.GetNonSharedViewModel("ContactVM") as ContactViewModel;

    if (vm == null)
    {
        throw new Exception("Couldn't create view model for contact.");
    }

    vm.SourceContact = contact;
    return vm;
}

public static IEnumerable<ContactViewModel> ToViewModels(this IEnumerable<Contact> contacts, IViewModelRouter router)
{
    return contacts.Select(contact => contact.ToViewModel(router)).ToList();
}

Notice the router is used to get a non-shared copy of the view model, then the contact is passed in. The list function simply applies the conversion to the entire list. Of course, the view model tag can be specified as a constant to avoid the "magic string" and make it easier to refactor down the road.

The main view model can now be tweaked to expose a list of view models:

public IEnumerable<ContactViewModel> ViewModels
{
    get { return Contacts.ToViewModels(Router); }
}

It's a very simple conversion using the helper extension methods. To ensure the enumerable is re-loaded anytime the underlying collection changes, simply add this after the observable collection is created:

Contacts.CollectionChanged += (o, e) => RaisePropertyChanged(() => ViewModels);

Next the XAML is updated to use the special converter:

<ListBox ItemsSource="{Binding ViewModels}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding Converter={StaticResource ViewConverter}}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

In this example, the binding is a list of contact view models. The special converter will inspect the binding, figure out the view model and find the corresponding view (the contact view we showed earlier), then create a new copy of the view and bind the view model. This could also have been done directly with the contact model if a view model wasn't being used. More importantly, if the list is type IViewModel it can contain different types of view models, and the converter will automatically find the appropriate view - this is a "View Model First" approach to binding but serves as a data template selector.

When the application is run, the non-shared views and view models spin up and bind as expected:

The full source code for Jounce and the example shown here is available from the Jounce CodePlex site.

Jeremy Likness

In this second installment about the Jounce framework, I'll share how to get started with Jounce and wire your first view bound to a view model.

The Jounce project is available online at http://Jounce.Codeplex.com.

Jounce injects itself as a service to the application. In my opinion, using IApplicationService is the right way to handle start up and shut down in a Silverlight application. It is also an opportunity to wire in configuration because a context is passed that contains the initialization parameters, as well as hook into events such as unhandled exceptions.

When you create a new application, you can blow away all of the junk you see in the App.xaml.cs code behind. Instead, you go into the XAML and insert the Jounce Application Service in a special section for application services:

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:Services="clr-namespace:Jounce.Framework.Services;assembly=Jounce.Framework" 
             x:Class="Jounce.App"
             >
    <Application.ApplicationLifetimeObjects>
        <Services:ApplicationService/>
    </Application.ApplicationLifetimeObjects>
</Application>

That's all Jounce needs to register and plug into the Silverlight application lifecycle. When the appplication first starts, it will call this method:

public void StartService(ApplicationServiceContext context)
{
    var logLevel = LogSeverity.Warning;

    if (context.ApplicationInitParams.ContainsKey(Constants.INIT_PARAM_LOGLEVEL))
    {
        logLevel =
            (LogSeverity)
            Enum.Parse(typeof (LogSeverity), context.ApplicationInitParams[Constants.INIT_PARAM_LOGLEVEL], true);
    }

    _mainCatalog = new AggregateCatalog(new DeploymentCatalog()); // empty one adds current deployment (xap)

    var container = new CompositionContainer(_mainCatalog);

    CompositionHost.Initialize(container);
    CompositionInitializer.SatisfyImports(this);

    if (Logger == null)
    {
        ILogger defaultLogger = new DefaultLogger(logLevel);
        container.ComposeExportedValue(defaultLogger);
    }

    DeploymentService.Catalog = _mainCatalog;
    _mefDebugger = new MefDebugger(container, Logger);
}

Here, Jounce is doing several things. It sets a default level for logging, but also checks the initialization parameters and overrides the level to whatever is set. This allows you to control the logging level by adding the parameter to the Silverlight object host. In this example, Jounce is being configured to log verbosely:

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
 <param name="source" value="ClientBin/Jounce.xap"/>
 <param name="onError" value="onSilverlightError" />
    <param name="initParams" value="Jounce.LogLevel=Verbose" />
 <param name="background" value="white" />
 <param name="minRuntimeVersion" value="4.0.50826.0" />
 <param name="autoUpgrade" value="true" />
 <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
   <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
 </a>
</object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>

Jounce wires in a default aggregate catalog to manage various deployment catalogs (this is what allows for dynamic XAP loading). There are two key things that also happen. First, Jounce declares an import for the logger contract that looks like this:

[Import(AllowDefault = true, AllowRecomposition = true)]
public ILogger Logger { get; set; }

The "allow default" tells MEF that null is fine and don't complain if nothing is exported for the contract. If you decide to implement your own logger and export it, it will be imported here and Jounce will use your custom logger. However, if you don't provide one, that's fine - Jounce can check the property for a null value and supply it's own default logger that simply writes to the debugger. This is exported to the container so future requests for a logger will pull in the default logger supplied by Jounce.

The MefDebugger is also important because it wraps the MEF container with some debug code that spits out lots of diagnostic information to help you troubleshoot what's going on with the Managed Extensibility Framework. If you debug the default application shipped with Jounce, you'll see plenty of activity in the debug window.

0/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger :: MEF: Found part: Jounce.ViewModels.WelcomeViewModel
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::    With import: Jounce.Core.ViewModel.BaseViewModel.EventAggregator (ContractName="Jounce.Core.Event.IEventAggregator")
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::    With import: Jounce.Core.ViewModel.BaseViewModel.Router (ContractName="Jounce.Core.ViewModel.IViewModelRouter")
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::    With import: Jounce.Core.ViewModel.BaseViewModel.Logger (ContractName="Jounce.Core.Application.ILogger")
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::    With export: Jounce.ViewModels.WelcomeViewModel (ContractName="Jounce.Core.ViewModel.IViewModel")
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::       With key: ViewModelType = Welcome
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::       With key: ExportTypeIdentity = Jounce.Core.ViewModel.IViewModel
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::    With export: Jounce.ViewModels.WelcomeViewModel (ContractName="Jounce.Core.ViewModel.IViewModel")
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::       With key: ViewModelType = Welcome
10/19/2010 6:44:29 AM Verbose Jounce.Core.MefDebugger ::       With key: ExportTypeIdentity = Jounce.Core.ViewModel.IViewModel

This is just one example of a "part" found and the resulting imports and exports. This is very valuable to track down why imports or exports might not be behaving the way you expect. Take a look at the source for the MefDebugger. It spins through all parts in the container, but then hooks into an event so that any time the container is rewired (such as when a dynamic XAP file is loaded) it will dump the changes for you as well.

The next important lifecycle event is the Starting method, called after the initialization but before the visual tree is completely wired. Take a look here:

public void Starting()
{
    Application.Current.UnhandledException += Current_UnhandledException;

    var viewInfo = (from v in Views where v.Metadata.IsShell select v).FirstOrDefault();

    if (viewInfo == null)
    {
        var grid = new Grid();
        var tb = new TextBlock
                        {
                            Text = Resources.ApplicationService_Starting_Jounce_Error_No_view
                        };
        grid.Children.Add(tb);
        Application.Current.RootVisual = grid;
        Logger.Log(LogSeverity.Critical, GetType().FullName,  Resources.ApplicationService_Starting_Jounce_Error_No_view);
        return;
    }

    Application.Current.RootVisual = viewInfo.Value;
    Logger.LogFormat(LogSeverity.Information, GetType().FullName,
                        Resources.ApplicationService_Starting_ShellResolved, MethodBase.GetCurrentMethod().Name,
                        viewInfo.Value.GetType().FullName);
    Logger.Log(LogSeverity.Information, GetType().FullName, MethodBase.GetCurrentMethod().Name);            

    EventAggregator.Publish(viewInfo.Metadata.ExportedViewType.AsViewNavigationArgs());
}

Jounce hooks into the unhandled exceptions and provides a method that basically raises a custom message. This is done using the Event Aggregator (more on that later) but makes it easy to subscribe to exceptions and even handle them in your code.

When you tag a view in Jounce, you can mark a view as the shell. This should only be done with one view. Jounce looks for that view and sets it to the root visual, or creates an error message and displays that instead.
The view metadata is imported to the application service like this:

[ImportMany(AllowRecomposition = true)]
public Lazy<UserControl, IExportAsViewMetadata>[] Views { get; set; }

Jounce then logs some messages and raises a navigation event. We'll cover navigation in Jounce later - the important thing to know is that this navigation event is what informs Jounce that it should go out and find any related view models and bind them to the view.

How did we get the view to appear as the shell?

[ExportAsView("Welcome",IsShell = true)]
public partial class Welcome
{
    public Welcome()
    {
        InitializeComponent();            
    }
}

Jounce gives you plenty of flexibility to tag your views and view models. The only rule is that each tag should be unique. Here, we're just using a "magic string" but in most applications (and you'll see the examples in the quick starts) constants can be defined instead. In this case, the view is tagged with the tag "Welcome" and set as the shell. That's all it takes to make that view the first view that appears.

Of course, the whole point of the framework is MVVM. In the Jounce default example, we create a simple view model that handles a welcome message but also kicks off an animation when loaded. The view model looks like this:

[ExportAsViewModel("Welcome")]
public class WelcomeViewModel : BaseViewModel 
{
    public WelcomeViewModel()
    {
        Title = "Welcome to Jounce!";            
    }

    private string _title;

    public string Title
    {
        get { return _title; }
        set
        {
            _title = value;
            RaisePropertyChanged(()=>Title);
        }
    }

    public override void _Activate(string viewName)
    {            
        GoToVisualState("WelcomeState",true);
    }
}

This view model is also tagged like the view. It can have a different tag than the view, because Jounce allows for the same view model to be bound to multiple views. What's important here is that it is tagged.

The base view model offers several services, including methods you can override when the view model is created for the very first time (_Initialize), anytime the view it is bound to becomes activate (_Activate) and anytime the view is deactivated (_Deactivate).

When the navigation event for a view is raised, Jounce intercepts this call and binds the view model and calls the appropriate methods.

Take a look at the view router. It is an event sink for the view navigation event - this allows it to receive any global messages sent for navigation:

public class ViewRouter : IPartImportsSatisfiedNotification, IEventSink<ViewNavigationArgs>

The view router in turn calls the ActivateView method on the ViewModelRouter. The method looks like this:

public bool ActivateView(string viewName)
{
    Logger.LogFormat(LogSeverity.Verbose, GetType().FullName, Resources.ViewModelRouter_ActivateView,
                        MethodBase.GetCurrentMethod().Name,
                        viewName);

    if (HasView(viewName))
    {
        var view = ViewQuery(viewName);

        var viewModelInfo = GetViewModelInfoForView(viewName);

        if (viewModelInfo != null)
        {
            var firstTime = !viewModelInfo.IsValueCreated;

            var viewModel = viewModelInfo.Value;

            if (firstTime)
            {
                viewModel.GoToVisualState =
                    (state, transitions) =>
                    JounceHelper.ExecuteOnUI(() => VisualStateManager.GoToState(view, state,
                                                                                transitions));
                _BindViewModel(view, viewModel);
                viewModel.Initialize();
            }
            viewModel.Activate(viewName);
        }

        return true;
    }
    return false;
}

As you can see, a view model is found to match the view and is bound (the view model router will look for LayoutRoot and bind the view model there ... if it can't find it, it will bind it to the parent control's DataContext). You can also see that Jounce binds an action called GoToVisualState that executes on the UI thread. This allows the view model to fire a visual state transition without referencing the view. In our example, the _Activate method is overridden to call:

public override void _Activate(string viewName)
{            
    GoToVisualState("WelcomeState",true);
}

This triggers a visual state transition and animations the "Welcome to Jounce" message.

There is one final piece missing. We never specified how to know that the welcome view model belongs with the welcome view. In Jounce, I decided against a traditional locator pattern to provide more flexibility. Instead, a binding is exported that maps a view model to a view. What's nice about this approach is that the binding can be consolidated in a class that holds all bindings for the application, or localized to the view so it is clear what view model the view is binding to. You could also write your own interface, such as a fluent or convention-based interface, and export bindings to the container to achieve the same result.

In the Welcome view, we mark the binding by exporting the tag for the view model and the tag for the view here:

[Export]
public ViewModelRoute Binding
{
    get
    {
        return ViewModelRoute.Create("Welcome", "Welcome");
    }
}

That's all there is to it! From your perspective, you had to:

  1. Add the Jounce Application service to the App.xaml
  2. Build your view model and tag it
  3. Build your view and tag it, then mark it as the shell
  4. Export a binding for the view model and the view

Jounce took care of all the rest.

The Jounce project is available online at http://Jounce.Codeplex.com.

Jeremy Likness

The purpose of this post is to provide an introduction to the Model-View-ViewModel (MVVM) pattern. While I've participated in lots of discussions online about MVVM, it occurred to me that beginners who are learning the pattern have very little to go on and a lot of conflicting resources to wade through in order to try to implement it in their own code. I am not trying to introduce dogma but wanted to pull together key concepts in a single post to make it easy and straightforward to understand the value of the pattern and how it can be implemented. MVVM is really far simpler than people make it out to be.

Why Even Care About MVVM?

Why should you, as a developer, even care about the Model-View-ViewModel pattern? There are a number of benefits this pattern brings to both WPF and Silverlight development. Before you go on, ask yourself:

  • Do you need to share a project with a designer, and have the flexibility for design work and development work to happen near-simultaneously?
  • Do you require thorough unit testing for your solutions?
  • Is it important for you to have reusable components, both within and across projects in your organization?
  • Would you like more flexibility to change your user interface without having to refactor other logic in the code base?

If you answered "yes" to any of these questions, these are just a few of the benefits that using the MVVM model can bring for your project.

I've been amazed at some conversations I've read online. Things like, "MVVM only makes sense for extremely complex UI" or "MVVM always adds a lot of overhead and is too much for smaller applications." The real kicker was, "MVVM doesn't scale." In my opinion, statements like this speak to knowledge and implementation of MVVM, not MVVM itself. In other words, if you think it takes hours to wire up MVVM, you're not doing it right. If your application isn't scaling, don't blame MVVM, blame how you are using MVVM. Binding 100,000 items to a list box can be just silly regardless of what pattern you are following.

So the quick disclaimer: this is MVVM as I know it, not MVVM as a universal truth. I encourage you to share your thoughts, experiences, feedback, and opinions using the comments. If you feel something is incorrect, let me know and I'll do my best to keep this post updated and current.

MVVM at a Glance

Let's examine the pieces of the MVVM pie. We'll start with the basic building block that is key for all applications: data and information. This is held in the model.

The Model

The model is what I like to refer to as the domain object. The model represents the actual data and/or information we are dealing with. An example of a model might be a contact (containing name, phone number, address, etc) or the characteristics of a live streaming publishing point.

The key to remember with the model is that it holds the information, but not behaviors or services that manipulate the information. It is not responsible for formatting text to look pretty on the screen, or fetching a list of items from a remote server (in fact, in that list, each item would most likely be a model of its own). Business logic is typically kept separate from the model, and encapsulated in other classes that act on the model. This is not always true: for example, some models may contain validation.

It is often a challenge to keep a model completely "clean." By this I mean a true representation of "the real world." For example, a contact record may contain a last modified date and the identity of the modifying user (auditing information), and a unique identifier (database or persistence information). The modified date has no real meaning for a contact in the real world but is a function of how the model is used, tracked, and persisted in the system.

Here is a sample model for holding contact information:

namespace MVVMExample
{
    public class ContactModel : INotifyPropertyChanged
    {
        private string _firstName;

        public string FirstName
        {
            get { return _firstName; }
            set
            {
                _firstName = value;
                RaisePropertyChanged("FirstName");
                RaisePropertyChanged("FullName");
            }
        }

        private string _lastName;

        public string LastName
        {
            get { return _lastName; }
            set
            {
                _lastName = value;
                RaisePropertyChanged("LastName");
                RaisePropertyChanged("FullName");
            }
        }

        public string FullName
        {
            get { return string.Format("{0} {1}", FirstName, LastName); }
        }

        private string _phoneNumber;

        public string PhoneNumber
        {
            get { return _phoneNumber; }
            set
            {
                _phoneNumber = value;
                RaisePropertyChanged("PhoneNumber");
            }
        }

        protected void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public override bool Equals(object obj)
        {
            return obj is ContactModel && ((ContactModel) obj).FullName.Equals(FullName);
        }

        public override int GetHashCode()
        {
            return FullName.GetHashCode();
        }
    }
}

The View

The view is what most of us are familiar with and the only thing the end user really interacts with. It is the presentation of the data. The view takes certain liberties to make this data more presentable. For example, a date might be stored on the model as number of seconds since midnight on January 1, 1970 (Unix Time). To the end user, however, it is presented with the month name, date, and year in their local time zone. A view can also have behaviors associated with it, such as accepting user input. The view manages input (key presses, mouse movements, touch gestures, etc) which ultimately manipulates properties of the model.

In MVVM, the view is active. As opposed to a passive view which has no knowledge of the model and is completely manipulated by a controller/presenter, the view in MVVM contains behaviors, events, and data-bindings that ultimately require knowledge of the underlying model and viewmodel. While these events and behaviors might be mapped to properties, method calls, and commands, the view is still responsible for handling it's own events and does not turn this completely over to the viewmodel.

One thing to remember about the view is that it is not responsible for maintaining its state. Instead, it will synchronize this with the viewmodel.

Here is an example view, expressed as XAML:

<UserControl x:Class="MVVMExample.DetailView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid x:Name="LayoutRoot" Background="White" DataContext="{Binding CurrentContact}">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="Name:" HorizontalAlignment="Right" Margin="5"/>
        <TextBlock Text="{Binding FullName}" HorizontalAlignment="Left" Margin="5" Grid.Column="1"/>
        <TextBlock Text="Phone:" HorizontalAlignment="Right" Margin="5" Grid.Row="1"/>
        <TextBlock Text="{Binding PhoneNumber}" HorizontalAlignment="Left" Margin="5" Grid.Row="1" Grid.Column="1"/>
    </Grid>
</UserControl>

Note that the various bindings are the integration/synchronization points with the viewmodel.

The ViewModel (Our Controller/Presenter)

The viewmodel is a key piece of the triad because it introduces Presentation Separation, or the concept of keeping the nuances of the view separate from the model. Instead of making the model aware of the user's view of a date, so that it converts the date to the display format, the model simply holds the data, the view simply holds the formatted date, and the controller acts as the liaison between the two. The controller might take input from the view and place it on the model, or it might interact with a service to retrieve the model, then translate properties and place it on the view.

The viewmodel also exposes methods, commands, and other points that help maintain the state of the view, manipulate the model as the result of actions on the view, and trigger events in the view itself.

MVVM, while it evolved "behind the scenes" for quite some time, was introduced to the public in 2005 via Microsoft's John Gossman blog post about Avalon (the code name for Windows Presentation Foundation, or WPF). The blog post is entitled, Introduction to Model/View/ViewModel pattern for building WPF Apps and generated quite a stir judging from the comments as people wrapped their brains around it.

I've heard MVVM described as an implementation of Presentation Model designed specifically for WPF (and later, Silverlight).

The examples of the pattern often focus on XAML for the view definition and data-binding for commands and properties. These are more implementation details of the pattern rather than intrinsic to the pattern itself, which is why I offset data-binding with a different color:

Model-View-ViewModel

Here is what a sample view model might look like. We've created a BaseINPC class (for "INotifyPropertyChanged") that has a method to make it easy for raising the property changed event.

namespace MVVMExample
{
    public class ContactViewModel : BaseINPC
    {
        public ContactViewModel()
        {
            Contacts = new ObservableCollection<ContactModel>();
            Service = new Service();
            
            Service.GetContacts(_PopulateContacts);

            Delete = new DeleteCommand(
                Service, 
                ()=>CanDelete,
                contact =>
                    {
                        CurrentContact = null;
                        Service.GetContacts(_PopulateContacts);
                    });
        }

        private void _PopulateContacts(IEnumerable>ContactModel> contacts)
        {
            Contacts.Clear();
            foreach(var contact in contacts)
            {
                Contacts.Add(contact);
            }
        }

        public IService Service { get; set; }

        public bool CanDelete
        {
            get { return _currentContact != null; }
        }

        public ObservableCollection<ContactModel> Contacts { get; set; }

        public DeleteCommand Delete { get; set; }

        private ContactModel _currentContact;

        public ContactModel CurrentContact
        {
            get { return _currentContact; }
            set
            {
                _currentContact = value;
                RaisePropertyChanged("CurrentContact");
                RaisePropertyChanged("CanDelete");
                Delete.RaiseCanExecuteChanged();
            }
        }
    }
}

This view model is obviously designed to manage a list of contacts. It also exposes a delete command and a flag to indicate whether delete is allowed (thus maintaining state for the view). Often the flag would be part of the command object, but the example is in Silverlight 3 which does not have native support for command binding, and I wanted to show a simple solution that didn't require a fancy framework. The view model here makes a concrete reference to the service, you would most likely wire in that reference externally or use a dependency injection framework. What's nice is we have the flexibility to build it like this initially and then refactor as needed. It fetches the list of "contacts" right away, which is a hard-coded list of me and someone a little more popular. The phone numbers, of course, are faked.

Let's get a little more specific and look at how this would be implemented in a sample application. Here is what an X-ray of a sample MVVM set up may look like:

MVVM Explained

So what can we gather from this snapshot?

First, the IConfig represents a configuration service (in a newsreader it may contain the account information and feeds that are being fetched), while the IService is "some service" - perhaps the interface to fetch feeds from RSS sources in a news reader application.

The View and the ViewModel

  • The view and the viewmodel communicate via data-binding, method calls, properties, events, and messages
  • The viewmodel exposes not only models, but other properties (such as state information, like the "is busy" indicator) and commands
  • The view handles its own UI events, then maps them to the viewmodel via commands
  • The models and properties on the viewmodel are updated from the view via two-way databinding

Two mechanisms that often factor into implementations of the pattern are triggers (especially data triggers) in WPF, and the Visual State Manager (VSM) in Silverlight. These mechanisms help implement the pattern by binding UI behaviors to the underlying models. In Silverlight, the VSM should be the primary choice for coordination of transitions and animations. Learn more about VSM.

The ViewModel and the Model

The viewmodel becomes wholly responsible for the model in this scenario. Fortunately, it's not alone:

  • The viewmodel may expose the model directly, or properties related to the model, for data-binding
  • The viewmodel can contain interfaces to services, configuration data, etc in order to fetch and manipulate the properties it exposes to the view

The Chicken or the Egg?

You might have heard discussion about view first or viewmodel first. In general, I believe most developers agree that a view should have exactly one viewmodel. There is no need to attach multiple viewmodels to a single view. If you think about separation of concerns, this makes sense, because if you have a "contact widget" on the screen bound to a "contact viewmodel" and a "company widget" bound to a "company viewmodel", these should be separate views, not a single view with two viewmodels.

A view may be composed of other views, each with its own viewmodel. Viewmodels might compose other viewmodels when necessary (often, however, I see people composing and aggregating viewmodels when in fact what they really want is messaging between viewmodels).

While a view should only have one viewmodel, a single viewmodel might be used by multiple views (imagine a wizard, for example, that has three views but all bind to the same viewmodel that drives the process).

View First

View first simply means the view is what drives the creation or discovery of the view model. In view first scenarios, the view typically binds to the view model as a resource, uses a locator pattern, or has the view model injected via MEF, Unity, or some other means. This is a very common method for managing views and view models. Here are some of my posts on the topic:

The example I've included with this post is view-first. The view is created, then the view model attached. In the App object, it looks like this:

private void Application_Startup(object sender, StartupEventArgs e)
{
    var shell = new MainPage();
    shell.LayoutRoot.DataContext = new ContactViewModel();
    RootVisual = shell;
}

In this example, I'm keeping it simple and not using any frameworks to wire in interfaces and implementations.

ViewModel First

ViewModel first is another method to wire the framework together. In this scenario, the viewmodel is responsible for creating the view and binding itself to the view. You can see an example of this in Rob Eisenberg's convention-based framework he discussed at MIX: Build your own MVVM Framework.

The take away here is there are multiple ways to skin the cat.

A Basic MVVM Framework

In my opinion, a basic MVVM framework really only requires two things:

  1. A class that is either a DependencyObject or implements INotifyPropertyChanged to fully support data-binding, and
  2. Some sort of commanding support.

The second issue exists in Silverlight 3 because the ICommand interface is provided, but not implemented. In Silverlight 4 commanding is more "out of the box." Commands facilitate binding of events from the view to the viewmodel. These are implementation details that make it easier to use the MVVM pattern.

Keep in mind there is very rich support for binding and behaviors in Blend and the free Blend SDK. You can watch my video, MVVM with MEF in Silverlight, to get an idea of how easy it really is to implement the MVVM pattern even without an existing framework in place. The post, MEF instead of Prism for Silverlight 3, shows how to build your own command objects.

With this example, I created a base class to handle the property changed events:

namespace MVVMExample
{
    public abstract class BaseINPC : INotifyPropertyChanged  
    {
        protected void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged; 

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

I also implemented a command. Typically you would have a more generic type of command to handle different situations, but again, for the sake of illustration, I simply created a delete command specific to the function it performs. I am using a message box to confirm the delete. If you require something more elegant like a ChildWindow, read the scenarios I describe below to better understand how to integrate a dialog box as a service within MVVM.

namespace MVVMExample
{
    public class DeleteCommand : ICommand 
    {
        private readonly IService _service;
        private readonly Func<bool> _canExecute;
        private readonly Action<ContactModel> _deleted;

        public DeleteCommand(IService service, Func<bool> canExecute, Action<ContactModel> deleted)
        {
            _service = service;
            _canExecute = canExecute;
            _deleted = deleted;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute();
        }

        public void Execute(object parameter)
        {
            if (CanExecute(parameter))
            {
                var contact = parameter as ContactModel; 
                if (contact != null)
                {
                    var result = MessageBox.Show("Are you sure you wish to delete the contact?",
                                                              "Confirm Delete", MessageBoxButton.OKCancel);

                    if (result.Equals(MessageBoxResult.OK))
                    {
                        _service.DeleteContact(contact);
                        if (_deleted != null)
                        {
                            _deleted(contact);
                        }
                    }
                }
            }
        }

        public void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        public event EventHandler CanExecuteChanged;
    }
}

This particular command uses a delegate to callback when it is done, but this would only allow for a single subscriber. A multicast delegate or event will be required if multiple consumers (or viewmodels) for the command exist.

In Silverlight 4, I can simply bind a button to the command using the Command tag. I built the example in Silverlight 3, which does not have native support. To create the binding, I made a simple trigger - again, specific to this project and for the sake of illustration - to invoke the command, so I can easily bind it in the XAML.

For the examples I've provided here, you can view the sample application. It is very simple and contains exactly one service and one view model with a "mock database." Two views bind to the same viewmodel, and you can click on a contact to see its details. You can also delete a contact.

I often receive complaints that blog examples are too simple. This is sufficiently complex to show a full app without depending on other frameworks, but certainly doesn't show multiple pages and types of views. The reason you don't see these as often from me is simply because I am a consultant and contractor, so I am constantly building these line of business frameworks and applications for customers, and am not at liberty to share their code. While I can build small examples for posts, I simply don't have the time to build a larger working model. It's something I'd certainly like to do, but just wasn't practical for the timing of this post.

You can download the source code for this example here.

You can also see it in action here (click on the names and try delete ... I simulated a slight delay for the initial load and the refresh after a delete).

Click here to view the example in a new window.

I think the easiest way to learn the pattern is by seeing a full application being built. I demonstrate this in MVVM with MEF in Silverlight. In that video, I build some simple viewmodels and show a view that is dynamically swapped based on user selection, and use MEF to wire everything up. A more complex scenario is then introduced in Part 2.

So what about those more complicated line of business solutions ... the ones that actually have more than one button, multiple views, and complex logic? That is beyond the scope of this post to cover in detail, but I'd like to tackle a few common scenarios and how I've solved them with MVVM.

Common MVVM Scenarios

In my experience, the idea of binding both commands and models or properties is straightforward. It's when you hit specific situations such as showing a dialog box or triggering an animation that MVVM may seem confusing. How do we solve these common problems?

List with Selection

How do you handle a combo box used for selection of a single, or multiple, items with MVVM? It's actually fairly straightforward. In fact, imagine a scenario where you have a combo-box that has a list of contact names, and another view on the same page that shows the contact details when selected. The ViewModel would look something like this, assuming I'm using MEF to wire dependencies (to show you a different way from the reference application):

public class ContactViewModel : BaseViewModel, IPartImportsSatisfiedNotification
{
    [Import] 
    public IContactService Service { get; set; }

    public ContactViewModel()
    {
       Contacts = new ObservableCollection<Contact>();
    }

    public ObservableCollection<Contact> Contacts { get; set; }

    private Contact _currentContact; 

    public Contact CurrentContact 
    { 
       get { return _currentContact; } 
       set
       {
          _currentContact = value;
          RaisePropertyChanged("CurrentContact"); 
       } 
    }

    public void OnImportsSatisfied() 
    {
       Service.FetchContacts(list =>
          {
             foreach(var contact in list)
             {
                Contacts.Add(contact);
             }
             CurrentContact = Contacts[0];
          });
    }
}

In this case, we import a service for getting contacts, wire in the list and set the current contact. The drop down binds to the Contacts collection. What's important, however, is that the selected item is also bound (this is where the view model maintains state). The binding would look like this:

...
<ComboBox ItemsSource="{Binding Contacts}" SelectedItem="{Binding CurrentContact,Mode=TwoWay}"/> 
...

This ensures whenever something is selected in the list, the current contact is updated. Remember that I mentioned multiple views might share the same viewmodel? In this case, the view for the contact details can use this same view model, and simply bind to the CurrentContact property.

Navigation

Navigation is a common issue to tackle. How do you manage navigation from an MVVM application? Most examples show only a single button or widget on the screen and don't tackle composite applications with multiple pages.

The short answer is that regardless of how you navigate (whether you use your own engine to pull in views, you use the navigation framework supplied by Silverlight, you use region management with Prism or a combination of all of these), you should abstract the mechanism behind an interface. By defining INavigation or something similar, navigation no longer becomes an MVVM problem. However you solve it, your viewmodel can import INavigation and simply navigate to or trigger the transition as needed.

My post on MEF instead of Prism shows how to do this with the Managed Extensibility Framework. Auto-discoverable views using a fluent interface covers mapping views to regions, and Dynamic module loading with Prism has a full solution using the navigation framework.

Dynamic Modules

This follows navigation. What if you have an extremely large application? It often doesn't make sense to load everything at once. You want the main menu and screne to appear, and then load other modules dynamically as they are needed. This cuts down on the initial time to get the application up and running, and also respects the user's browser and/or desktop memory and CPU.

The issue of dynamic modules isn't really specific to MVVM, but messaging between viewmodels and across modules is of course important. For these, I do believe it makes more sense to look at existing frameworks like MEF and Prism that solve the specific issue. Prism has modules that can be loaded "on demand," and MEF offers a deployment catalog that allows for dynamic loading of XAP files. Prism's solution for messaging across the application is the event aggregator. I talk more about frameworks and solutions for these types of problems in the appendix when I cover existing frameworks that are available to use "out of the box."

Dialog

A common UI pattern is the dialog box (similar to the message box, but expects a reply). I've seen a few people trip over how this can be implemented using both MVVM and the restriction by Silverlight that all code must be asynchronous.

The easiest solution in my opinion is to abstract the dialog behind an interface and provide a callback for the response. The view model can import the dialog, then based on some change in state or a command, trigger the dialog service. The callback will return the response and then the view can process accordingly.

For a fuller explanation, read Simple Dialog Service in Silverlight.

Animations

This is a very common problem to tackle: how can changes triggered either in the UI or the backend kick off animations and other transitions?

There are several solutions to the problem. Here are a few examples of how to solve the problem:

Configuration or Global Values

Another issue I see raised quite often is how to deal with global variables and configuration information. Again, this is less an MVVM problem and more a general architecture consideration. In most cases, you can expose configuration with an interface (IConfiguration) and then wire up an implementation with your configuration values. Any viewmodel that requires the information simply imports the implementation, whether via MEF, Unity, or some other mechanism, and only one copy of the class is kept (Singleton pattern, although most likely managed by the container and not the class itself).

Asynchronous Processes

One point of confusion with Silverlight is that it forces service calls to be asynchronous. This can seem strange when building a viewmodel: when do you trigger the call, and how do you know it is complete? Typically, this is managed by registered to an event when the process is complete, and binding the results. I prefer to hide the implementation details of the events behind a simple Action function. Read Simplifying Asynchronous Calls in Silverlight using Action for an example of this.

Sometimes you may have a more complex workflow that requires multiple asynchronous calls to execute and complete prior to continuing. If that is the case, you might want to look into a mechanism for making it easy to code and read the sequential workflow. This post will help you understand one solution using coroutines, and this post describes how to use an existing robust framework to manage those calls with thread safety, error handling, and more.

Huge Datasets

Finally, I've heard claims that MVVM doesn't handle large datasets well. I would argue it is certain implementations that have this issue, not the pattern itself. The solution is often to page the data, but I find many people approach the problem incorrectly. For some reason, developers want to insist paging is a function of the database and should be isolated to the data access layer. The simple fact that you have a UI element with "current page" and "total pages" suggested it is not just an artifact of the database, but participates in all layers of the application and should be managed as such.

In the most primitive form, you can create a collection that grows as the user pages. If your data is small, you might pull a very large collection and keep it in the Silverlight client, but use a virtualized panel to display the information (the problem with some panels is that they create a control for every bound data element, which can crush performance - virtualized panels only create enough controls to fill the visible window on the screen).

Technologies like WCF RIA support LINQ queries. These queries contain extension methods that allow you to grab only the first few items in a list, rather than fetching the full list at once. The framework also provides helper classes like the PagedCollectionView to help filter, sort, and page data.

What MVVM Isn't

No discussion would be complete unless we talked about what MVVM isn't.

MVVM isn't a complete framework. It's a pattern and might be part of a framework, but it's only a piece of the overall solution for your application architecture. It doesn't address, and doesn't really care, about what happens on your server or how your services are put together. It does stress separation of concerns, which is nice.

I bet that nowhere in this article did you read a rule that stated, "With MVVM, code behind is not allowed." This is a raging debate but the pattern itself doesn't tell you how to implement your view, whether that is with XAML, code-behind, or a combination of the two. I would suggest that if you are spending days writing something just to avoid minutes of code-behind, your approach is wrong.

It is not required for Silverlight or WPF. I believe that line-of-business, data-driven, and forms-based applications are prime candidates for MVVM. Games, entertainment websites, paint programs, and others may not make sense. Be sure you are using the right tool for the right job.

MVVM is not supposed to slow you down! All new patterns and frameworks come with a learning curve. You'll have to accept that your developers need to learn and understand the pattern, but you should not accept that your entire process suddenly takes longer or becomes delayed. The pattern is useful when it accelerates development, improves stability and performance, reduces risk, and so forth. When it slows development, introduces problems and has your developers cringing whenever they hear the phrase, "design pattern" you might want to rethink your approach.

Conclusion

OK, we're done! That's it. I hope you've learned why MVVM is so powerful for Silverlight and WPF applications, what the pattern looks like and even examples of solutions for common problems that MVVM can solve. Now, what are your thoughts and comments?

Jump to Appendix A: Historical Patterns

Jump to Appendix B: Existing Frameworks

A very special thanks to the community members who took time out of their busy schedules to review and provide preliminary feedback and suggestions for this article: (in alphabetical order)

Appendix A: Some Historical Patterns

Model-View-Controller (MVC)

This software architecture pattern was first described in the context of Smalltalk at Xerox in 1979. If you are interested, you can download some of those original papers (PDF format) by clicking here (PDF).

Model-View-Controller (MVC)

Model-View-Presenter (MVP)

In 1996, the Model-View-Presenter pattern (PDF) was introduced to the world. This pattern builds on MVC but places special constraints on the controller, now called the presenter. A general overview looks like this:

Model-View-Presenter

Martin Fowler describes this pattern with two flavors: the Supervising Controller/Presenter and the Passive View. Here is how Microsoft describes: MVP.

Presentation Model

In 2004, Martin Fowler published his description of the Presentation Model. The summary is quite succinct: "Represent the state and behavior of the presentation independently of the GUI controls used in the interface." As you can see, MVVM is a specialized form of this pattern:

Presentation Model

Appendix B: Pre-existing MVVM Frameworks

Now that we have an idea of what MVVM is all about, you don't have to re-invent the wheel. There are a number of out of the box frameworks that exist which implement MVVM. In no particular order:

The MVVM Light Toolkit

This is a very popular toolkit that contains support out of the box for base viewmodels, commands, messaging, and project templates to get started. It supports both WPF and Silverlight projects.

SilverlightFX

The stated goals for this framework are to enable concise declarative specification of user interfaces, enable easier separation of view and code, and provide a lean framework.

Caliburn

Caliburn is a popular viewmodel-first framework that supports both WPF and Silverlight. More than just MVVM, however, it is a full application framework.

nRoute

Another MVVM framework, this library is unique for the "reverse commands" that allow binding commands to events in the view as opposed to having the view simply send commands to the viewmodel.

MicroModels

A very lean and lightweight approach to MVVM.

Composite WPF/Prism

Despite the name, this framework supports both WPF and Silverlight. While not directly providing MVVM implementations, it does provide much support and guidance for composing applications including commands, event aggregation, region management, and more.

While this is certainly not an exhaustive list by any stretch of the imagination, hopefully it gives you an idea of the open source community support available for MVVM and that there are existing mature frameworks that you can choose from to accelerate your development.

Jeremy Likness

This is a video tutorial to introduce beginners to how to use both MVVM (Model-View-ViewModel) and MEF (Managed Extensibility Framework) with Silverlight (should work for versions 3 and 4). Of course, some "veterans" may want to watch as well in case you've missed some of the fundamentals, or have a clever way to do something that you can share in the comments for future visitors to the page.

In this edition, I build a simple application that allows the user to check a preference on the screen (whether they prefer squares over circles) and then displays a square or a circle. We use MVVM and wire everything together with MEF.

Download the source code: MEFMVVMDemoSln.zip

Click here to watch the video directly if it doesn't appear in the frame below (recommended to watch in full screen): Watch the video in a separate window

Here is the final application:

Download the source code: MEFMVVMDemoSln.zip

Jeremy Likness

In yesterday's post about Decoupled ChildWindow Dialogs in Silverlight using Prism, I demonstrated a way to use EventAggregator to decouple the implementation of a dialog from the code that requires the confirmation. In one example, I showed a code-behind click event that fired off the process, something like this:

private void Button_Delete_Click(object sender, System.Windows.RoutedEventArgs e)
{
    Button src = e.OriginalSource as Button;
    if (src != null)
    {
        _eventService.GetEvent<MessageBoxEvent>().Publish(
            MessageBoxPayload.GeneratePayLoad(src.DataContext, true, "Please Confirm", "Are you sure you wish to delete this item?",
                                      DeleteItem));
    }
}    

This, in my opinion, is way too much information for a view to know and understand. It has to know about my event aggregator service? Is that really necessary?

If you are not familiar with the Model-View-ViewModel (MVVM) pattern, you'll want to Google/research it now. It is important because a lot of the marshalling of data will happen in the ViewModel, and the view will simply be bound to the view model.

Prism provides a commanding interface that works well with buttons. You can use an attached property to bind the click to a command (which is in turn a DelegateCommand). The command will disable the button if it can't execute and fire when the button is clicked. The button becomes a binding, like this:

...
<Button Commands:Click.Command={Binding SearchCommand} .../> 
...

In the view model, the SearchCommand is defined like this:

...
public DelegateCommand<object> SearchCommand { get; set; }
...
SearchCommand = new DelegateCommand<object>(o => 
   _service.GetEventService().GetEvent<SearchEvent>().Publish(
      SearchCriteria),o => _CanSearch());

In this example, we are assuming the form fields are bound to a search criteria object in the view model. Presumably once the criteria meet our validation requirements, _CanSearch will return true, the button will be enabled, and the command will publish an event to begin the search using the populated criteria entity.

While I intend to dig more in depth in that pattern, I wanted to present something I believe is a common issue and describe how I addressed it. In this case, the view model contains the search criteria as well as a collection of objects for the results grid. This becomes problematic with binding, because my grid row is bound to the item in the list, not the view model itself. Unfortunately, Silverlight does not support (to my knowledge) the relative binding syntax available in WPF, so it can be troublesome to try to bind the click in the grid to a command.

If there is a simple way to do this I'd love to learn more, but any examples I've seen were fairly complex to maintain the "purity" of leaving everything out of the code behind. Me? I'm a bit more pragmatic. I'd rather go ahead and bind the click event (I know, some of you are shuddering ... that means a code behind ...) like I did above. However, there is a compromise!

Instead of making my view aware of the event aggregator service, I can do a bit better. The view model already knows about the service. Let's assume we could bind directly to a command. We'll create a command like this, in the view model:

public DelegateCommand<MyEntity> DeleteCommand { get; set; }

We can then wire the command to publication of a delete event:

DeleteCommand = new DelegateCommand<MyEntity>(
                _service.GetEventService().GetEvent<DeleteMyEntityEvent>().Publish, o => true);

Notice we don't supply parameters to Publish. That's because our event is already wired to act on an instance of MyEntity, and so the event will fire and pass that entity as a parameter.

Now we can clean up our code behind to look like this:

private void Button_Delete_Click(object sender, System.Windows.RoutedEventArgs e)
{
    Button src = e.OriginalSource as Button; 
    if (src != null)
    {
        MyEntity entity = src.DataContext as MyEntity;
        if (entity != null)
        {
            if (_ViewModel.DeleteCommand.CanExecute(entity))
            {
                _ViewModel.DeleteCommand.Execute(entity);
            }
        }
    }
}

So, it's not "pure" in the sense that I do end up with code behind ... but ask me, do I really care? Is it all that bad? The view is aware of the view model, so why not allow it to response to what views do well (view events) and marshall them to the view model? The implementation of the command is still hidden from view.

With some clever attached properties, we could also make the button disable if CanExecute is false, and because of data virtualization we'd only be evaluating it for the grid items that are in the view.

Jeremy Likness