backgroundTop
backgroundTop
Front Page
GreenBackgroundTop

Model-View-View-Model Pattern Overview

ViewModel (MVVM) in Raw Silverlight 2

The Model-View-ViewModel (MVVM or ViewModel) is a pattern for separating concerns in technologies that use databinding. For Silverlight 2, it can help to make more maintainable applications by removing much of the code in the code-behind files and allowing full testing of business logic. This video shows how to do a simple implementation of MVVM in Silverlight 2 without additional helpers (like Prism, Silverlight.FX, etc.).

erikmork

4k Votes

GreenBackgroundBottom
 

Important Code

Mark as Inappropriate Content

This video is licensed under a Creative Commons License.

Creative Commons License Download the Video

Information From the Video

GreenBackgroundTop

MSDN Article by Shawn Wildermuth

This video is based on Shawn's article. See the References section for a link.
GreenBackgroundBottom
 
GreenBackgroundTop

Reference Application

Shawn has written an open source reference application that uses MVVM. See the References section for a link to the source.
GreenBackgroundBottom
 
GreenBackgroundTop

Model - Game Catalog Class

The Game Catalog uses ADO.NET Data Services to access the Game information.
GreenBackgroundBottom
  public class GameCatalog : IGameCatalog
  {
    Uri theServiceRoot;
    GamesEntities theEntities;
    const int MAX_RESULTS = 50;

    public GameCatalog() : this(new Uri("/Games.svc", UriKind.Relative))
    {
    }

    public GameCatalog(Uri serviceRoot)
    {
      theServiceRoot = serviceRoot;
    }
 
GreenBackgroundTop

The Model Interface

The model implements an interface. Note that there's support for asynchronous firing of events. This is key in Silverlight since it is inherently asynchronous. Also, notice that this makes it trivial to swap in a Mock class to simulate the catalog for testing purposes.
GreenBackgroundBottom
  public interface IGameCatalog
  {
    void GetGames();
    void GetGamesByGenre(string genre);
    void SaveChanges();

    event EventHandler<GameLoadingEventArgs> GameLoadingComplete;
    event EventHandler<GameCatalogErrorEventArgs> GameLoadingError;
    event EventHandler GameSavingComplete;
    event EventHandler<GameCatalogErrorEventArgs> GameSavingError;
  }
 
GreenBackgroundTop

ViewModel

The ViewModel sits on top of the Model and provides facilities for easy binding for the View. In this case, the Games collection is exposed. The idea is that the ViewModel shapes the data and puts it into a convenient position for the View to databind against.
GreenBackgroundBottom
 public ObservableCollection<Game> Games
    {
      get
      {
        return theGames;
      }
    }
 
GreenBackgroundTop

ViewModel Testability

Here, the ViewModel is constructed using a Dependency Injection pattern for the Model. There are other options (Service Locator, etc.), but this loose coupling allows us to easily test the ViewModel.
GreenBackgroundBottom
    public GamesViewModel(IGameCatalog catalog)
    {
      theCatalog = catalog;
      theCatalog.GameLoadingComplete += 
        new EventHandler<GameLoadingEventArgs>(games_GameLoadingComplete);
      theCatalog.GameLoadingError += 
        new EventHandler<GameCatalogErrorEventArgs>(games_GameLoadingError);
    }
 
GreenBackgroundTop

View

In this case, the View puts the ViewModel (it can take an empty constructor) in a Resources section. This allows easy binding to the ViewModel.
GreenBackgroundBottom
  <UserControl.Resources>
    <data:GamesViewModel x:Key="TheViewModel"
                         d:IsDataSource="True" />
  </UserControl.Resources>
 
GreenBackgroundTop

Code-Behind

Without helpers (Prism, etc.), there isn't a Commanding interface in Silverlight 2. This means that we still have some code in the code-behind to propagate user intentions to the ViewModel.
GreenBackgroundBottom
void genreComboBox_SelectionChanged(object sender,
                                        SelectionChangedEventArgs e)
    {
      string item = genreComboBox.SelectedItem as string;
      if (item != null)
      {
        LoadGames(item);
      }
    }
 
GreenBackgroundTop

Testing of the ViewModel

The ViewModel can easily be tested with the Silverlight Unit Test Framework.
GreenBackgroundBottom
[TestMethod]
    [Description("Test Successful LoadGamesByGenre from the ViewModel")]
    [Asynchronous]
    public void TestLoadGamesByGenre()
    {
      bool loadComplete = false;

      GamesViewModel viewModel = new GamesViewModel(new MockGameCatalog());
      viewModel.LoadComplete += (s, e) =>
      {
        loadComplete = true;
      };
      viewModel.LoadGamesByGenre("Family");

      EnqueueConditional(() => loadComplete);

      EnqueueCallback(() =>
      {
        Assert.AreNotEqual(viewModel.Games, null, "Expected games list not to be null.");
      });

      EnqueueCallback(() =>
      {
        Assert.IsTrue(viewModel.Games.Count > 0, "Expected games list have results.");
      });

      EnqueueTestComplete();
    }
 
 
GreenBackgroundTop

References

Shawn Wildermuth's ViewModel article

This article forms the basis for the screencast. It gives a great walkthrough of the need for the MVVM pattern and the implementation of the pattern.

Reference ViewModel Application

This is the companion code to the article. It's a clean, open source implementation of the ViewModel pattern.

Shawn's Blog

Shawn's blog is a great source of Silverlight (and other) information.

Silverlight Unit Test Framework

This is an open source testing framework for Silverlight. It's recommended for any Silverlight project.

GreenBackgroundBottom
backgroundBottom
backgroundBottom