Second Stanza

July 24, 2010

MVVM – MEF – Reactive Data Grid – Part II

Filed under: .NET Development, MEF, MVVM, Rx Extensions, Silverlight — Tags: — dfbaskin @ 11:12 pm

The MVVMGrid application is architected using the Model-View-ViewModel (MVVM) pattern. So here are the parts:

  • GridView.xaml – this is the view containing the data grid. Visual elements are bound to data contained within the GridViewModel. The GridView knows about the properties that the GridViewModel exposes.
  • GridViewModel – this is the view model which is used as the DataContext of the GridView. The GridViewModel knows nothing about the GridView class.
  • GridData, ViewSettings, etc. – these are classes that define the data model that the application uses.
  • GridService – this is the class that provides the services to fetch the grid data and the view information.

We use the Managed Extensibility Framework (MEF) to stitch these pieces together. First, we need to create a CompositionContainer to handle the imports and exports of the various components. In this application, we only need to look in the one assembly for components, so only a single AssemblyCatalog is needed.

    public partial class App : Application
        private CompositionContainer partsContainer;

        public UserControl MainView { get; set; }

        public App()
            this.Startup += this.Application_Startup;
            this.Exit += this.Application_Exit;
            this.UnhandledException += this.Application_UnhandledException;


        private void Application_Startup( object sender, StartupEventArgs e )
            partsContainer = new CompositionContainer( new AssemblyCatalog( typeof( App ).Assembly ) );
            partsContainer.SatisfyImportsOnce( this );

            RootVisual = MainView;

Normally in Silverlight, we would set our RootVisual to a new UserControl we create in the application startup. Here, we allow MEF to find our root visual for us. How does it know which UserControl to create? The App class defines an Import attribute with a type of UserControl. The SatisfyImportsOnce method goes into the catalog we’ve supplied to it and finds a UserControl that is marked for export. Our GridView control is marked with the Export attribute and thus MEF is able to find it.

    public partial class GridView : UserControl
        public GridViewModel ViewModel
            get { return DataContext as GridViewModel; }
            set { DataContext = value; OnViewModelChanged(); }

Similarly, our GridViewModel is imported into our GridView, setting it as the DataContext for the view and thus enabling the data binding to work. The GridViewModel then imports the GridService.

    public class GridViewModel : INotifyPropertyChanged, IPartImportsSatisfiedNotification
        public GridService Service { get; set; }

Notice that the GridViewModel implements a couple of important interfaces, INotifyPropertyChanged and IPartImportsSatisfiedNotification. The first interface is used in data binding.  When properties on the GridViewModel change, the PropertyChanged event is fired. This allows data bindings to know that the data that is bound has changed and the user interface element needs to be updated.

The second interface is related to MEF. If an exported component implements this interface, then MEF will call the OnImportsSatisfied method on the object when all of the imports for the object have been satisified and the object is safe to use. In our application, we use this method to begin retrieving the data from our services that will be used in the data grid.

The source code for this project can be downloaded from CodePlex.


Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at

%d bloggers like this: