Wintellect  

Browse by Tags

All Tags » mvvm   (RSS)

In the first part of this series, I demonstrated a very simple project that used MVVM (Model-View-ViewModel) along with the Managed Extensibility Framework to produce a simple screen that toggled between a square and a circle.

In this next video, I am re-designing the original project. This video starts with the original solution, but then I rework the code, using metadata, to turn the shapes into plugins. I duplicate the original effort with the new design (using a combobox instead of a checkbox because now we can support 1 ... n plugins) and then show how easy it is to add a new plugin with the architecture.

Download the source code for this project.

Here is the final application:

Download the source code for this project.

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

Series recap:

In the final part of this series, I will show a dynamically loaded module (using PRISM) that takes full advantage of MEF.

Here is a preview of the final product, illustrating the different modules and areas I have pulled together to demonstrate (click for a full resolution view):

Download the Source for this Example

Why even bother with dynamic modules? Dynamic module loading can be a powerful way to build scalable (and more stable) applications in Silverlight. By creating dynamic modules, you ensure the user only loads what they need, when they need it. The dynamic module only comes into play when the user demands a feature that requires the module.

Before we dive into the new MEF-based module, let's break down a few best practices when using dynamically loaded modules:

  • The best option I've found for this so far is to use PRISM's "on demand" functionality for loading modules.
  • Typically, you will want to put your main dependencies in the "main" or "host" Silverlight project.
  • Create a new dynamic module by adding a Silverlight Application project, not a Silverlight Class Library.
  • Use a XAML catalog to reference the dynamic modules. This gives PRISM something to resolve when the new module is requested, but avoids direct dependencies on the satellite modules by the main application.
  • When referencing projects or DLLs that are part of the main application in a satellite module, be sure to set "copy local" to false. This ensures these are not compiled into the XAP, because the module can leverage the fact that the main module has already loaded the dependencies. This leads to very lightweight XAP files.

When everything comes together as planned, you can scan traffic with a tool like Fiddler to see what happens. Take a look at this example. Here, you can clearly see the satellite modules are loaded dynamically. In fact, the MEF module, which displays a list and dynamically displays a child view, weighs in at only 5,000 bytes!

Click here to view the Fiddler snapshot

I started by adding a new Silverlight Application and calling it MEFModule.

The MEF ViewModel

The MEF view model looks like this:


[Export]
public class MoreStuffViewModel : IPartImportsSatisfiedNotification
{        
    private IService _service; 

    [Import]
    public IService Service
    {
        get { return _service; }
        set
        {
            _service = value;
            if (_service != null)
            {
                _service.GetMoreStuff(_ServiceLoaded); 
            }
        }
    }

    [ImportMany("MoreStuff",AllowRecomposition=true)]
    public List<string> ImportedStuff { get; set; }

    [Import]
    public IRegionManager RegionManager { get; set; }

    public DelegateCommand<object> DynamicViewCommand { get; set; }

    [Import("DynamicView")] 
    public object DynamicView { get; set; }

    private ObservableCollection<string> _listOfMoreStuff;

    public MoreStuffViewModel()
    {
        // initialize all lists
        _listOfMoreStuff = new ObservableCollection<string>();
        DynamicViewCommand = new DelegateCommand<object>(o =>
            {
                RegionManager.RegisterViewWithRegion("MainRegion", () => DynamicView);
            });
    }

    private void _ServiceLoaded(List<string> values)
    {
        foreach (string value in values)
        {
            _listOfMoreStuff.Add(value);
        }
    }
       
    public ObservableCollection<string> ListOfMoreStuff 
    {
        get
        {
            return _listOfMoreStuff;
        }

        set
        {
            _listOfMoreStuff = value; 
        }
    }

    #region IPartImportsSatisfiedNotification Members

    public void OnImportsSatisfied()
    {
        foreach (string importedValue in ImportedStuff)
        {
            _listOfMoreStuff.Add(importedValue);
        }
    }

    #endregion
}

I've purposefully loaded this view model with tons of goodies to help understand and take advantage of MEF to its fullest. You'll notice two things right away about the view model: it is exported using the Export attribute, and it implements an interface called IPartImportsSatisfiedNotification. When you implement this interface, MEF will automatically call OnImportsSatisfied, allowing you to react to the new imports.

You'll notice I have a collection called ImportedStuff that imports a contract with a magic string (tip: in a production project this would probably be a type or an enumeration or at least a static class with a constant to allow for type checking) called MoreStuff. We'll give this collection what it needs somewhere else, for now it is simply waiting for imports and when those imports are satisfied, we merge them into our master ListOfMoreStuff collection.

We also reference IService. If you remember, when we set that up back in part 1, we went ahead and added an Export tag. Here, we import it. Notice that on the setter, when the import happens, I go ahead and call the GetMoreStuff method, which returns me the Spanish numbers. When these are loaded, we merge them into our master ListOfMoreStuff. So the list will contain the results of the service call and any MoreStuff imports we may find.

We also want to dynamically display another view, but we don't know what that view is yet. Remember in part 2 I explicitly set the export value of IRegionManager using Unity to resolve it? This is where we will import it!

The DynamicViewCommand gives us a command to bind to in order to show that view. The view gets imported with another magic string (again, just stating I know we don't like them, but they are there for the sake of brevity in this example only) called DynamicView. In the constructor for the view model, we bind the command to a call to RegisterViewWithRegion and pass in the dynamic view.

This demonstrates how powerful MEF really is: we are able to specify an action to dynamically show a view here in the view model without any prior knowledge of where the view is or even what it is composed of!

The rest of the view model code simply initializes lists, combines them, etc. We've got our view model in place. How about some views that use it?

The MEF Views

In the views folder, I created two views. The first or "main" view is simply called MoreStuffView and it binds to the ListOfMoreStuff collection as well as the dynamic view command:


<ListBox ItemsSource="{Binding ListOfMoreStuff}">
   <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<Button Grid.Column="1" cal:Click.Command="{Binding DynamicViewCommand}" Content="Add View"/>

The code behind requires two pieces: first, we need to import the view model and bind it:


[Import]
public MoreStuffViewModel ViewModel
{
   get { return (MoreStuffViewModel)LayoutRoot.DataContext; }
   set { LayoutRoot.DataContext = value; }
}

Next, we need to call our friend, the PartInitializer class, to satisfy all of the imports in the constructor:


public MoreStuffView()
{            
    InitializeComponent();           
    PartInitializer.SatisfyImports(this);                
}

And that's it ... all of the services, exports, etc will be wired in elsewhere. I created a second view called DynamicView. This view simply contains a text block that indicates it was dynamically loaded. Remember how we had our "magic string" import for a view in the view model? Here, we will export the dynamic view in the code behind. There is only one change to the auto-generated code behind file, and that is to add the Export tag:


[Export("DynamicView")]
public partial class DynamicView : UserControl
{
    public DynamicView()
    {
        InitializeComponent();
    }
}

That's it for the view model and the views!

Providing Exports

The exports can obviously be supplied in a variety of ways. For this example, I simply created a class and exported a few values to demonstrate that the imports were working and merging with the main list:


public class MoreStuffExports
{        
    [Export("MoreStuff")]
    public string Item1
    {
        get { return "MEF Export 1"; }
    }

    [Export("MoreStuff")]
    public string Item2
    {
        get { return "MEF Export 2"; }
    }            
}

The MEF Module Initializer

Now it's time to wire everything together. There is actually almost nothing to the module initializer class. Because we base it on the PartModule we defined in the last post, the MEF-specific actions happen as part of the base class. In this class, we simply register the main view:


public class MEFInit : PartModule
{
    IRegionManager _regionManager;

    public MEFInit(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    #region IModule Members

    public override void Initialize()
    {
        base.Initialize(); // gotta call base for the MEF magic to happen
        _regionManager.RegisterViewWithRegion("MainRegion", typeof(MoreStuffView));
    }

    #endregion
}

That's it!

Conclusion

The goal of this this small series is to demonstrate how well PRISM and MEF work together, and how accessible modular and extensible applications can be in Silverlight 3. You've learned several ways to marry the view model to the view using different types of dependency injection containers and patterns. You've also seen how to take advantage of dynamically loaded modules to create application extensions that have an extremely small footprint but can easily integrate with the flexibility provided by both Unity and MEF in the context of PRISM.

Download the Source Code for this example

Jeremy Likness

This post explores how to manage multiple view models across modules in a Prism-based Silverlight application.

One powerful feature of Prism is the ability to dynamically load modules. This allows reduction of the XAP file size, as well as encourages a smaller memory footprint as certain modules are not brought into the application until they are needed. A common issue I find developers struggle with is the consistent use of view models. I've seen some elegant solutions that involve storing values in isolated storage to move the values between modules (elegant, but overkill) when in fact a common view model shared between modules would have been fine.

I'm going to assume you are familiar with Prism and know how to build an application that dynamically loads modules as they are accessed. You may want to refer to my article Dynamic Module Loading with Silverlight Navigation if you need more background information.

Assume you have a project that is dynamically loading modules and injecting them into the shell. For my example, I'm going to assume the application does not require deep linking, so it is not based on the navigation framework (it could be fit easily). In order to facilitate my own navigation, I create a navigation service. The navigation service is a singleton and has the module manager injected to it. It contains an enumeration of controls to display, and a "module map" that maps the control to the module the control lives in. It also exposes a "view changed" event that it fires with the enumeration whenever a new view is navigated to.

The logic is quite simple (in this example, my enumeration is passed in as view, and the value of the enumeration maps nicely to the index of an array of modules that host views). MODULEINIT is just a shell based on the module naming convention, for example "MyApp.Module{0}.ModuleInitializer" or similar.

The module manager is injected in the constructor. Each time we navigate to a view, we call this so the module can be loaded if it hasn't been already. Prism keeps track of loaded modules and won't try to pull the XAP across the wire more than once.

_moduleManager.LoadModule(string.Format(MODULEINIT,_moduleMap[(int)view]));
            
EventHandler<ViewChangedEventArgs> handler = ViewChanged;
            
if (handler != null)
{
   ViewChangedEventArgs args = new ViewChangedEventArgs(_currentView, view);
   handler(this, args); 
}

As you can see, very straightforward. We remember the current view and send that with the new view to the event. The views themselves can register to the event. If the views are built with a VisualStateGroup to handle swapping them into and out of view, then the logic is simply: if I am the old view, go to my hidden state, else if I am the new view, go to my visible state. Then the views can live in an ItemsControl with only one view showing at a time.

For my views, I create a ViewBase class that is, in turn, based on UserControl. This lets me manage some common housekeeping for the views that will be bound to view models. First, I exposed a protected method called _ViewBaseInitialize to call after the component is initialized. This takes in the view model and binds it, as well as wires into the navigation change event. I know some people won't like injecting the view model and there are certainly other ways to marry the view and its model, but for our example this will do.

Our logic looks simply like:

protected void _ViewBaseInitialize(object viewModel)
{
   Loaded += (o, e) =>
      {
         MasterModel model = DataContext as MasterModel;
         model.Navigation.ViewChanged += new EventHandler<ViewChangedEventArgs>(nm_ViewChanged);
                
         if (viewModel != null)
         {
            model.ModuleViewModel = viewModel;
         }
      };

      if (currentView.Equals(e.OldView))
      {
         VisualStateManager.GoToState(this, "HideState", true); 
      }
      else if (page.Equals(e.NewView))
      {
         VisualStateManager.GoToState(this, "ShowState", true);
      }
}

You'll note the introduction of the MasterModel. This view model is bound at the shell level, so it is available to all of the views hosted in that shell. Typically, a shell as a Grid or similar item as the root layout panel, so in my bootstrapper I handle wiring up the master view model:

protected override DependencyObject CreateShell()
{
    Container.RegisterType<NavigationManager>(new ContainerControlledLifetimeManager());
    NavigationManager nm = Container.Resolve<NavigationManager>();
  
    Container.RegisterType<MasterModel>(new ContainerControlledLifetimeManager());           
               
    Shell shell = Container.Resolve<Shell>();
    Application.Current.RootVisual = shell;
    
    nm.NavigateToView(NavigationManager.NavigationPage.Login);
    
    return shell; 
}

Because the constructor of the master model takes in a "navigation manager" instance, it receives the instance we just configured. Likewise, the shell will receive the instance of the view model and bind that to the data context of its main grid.

For all practical purposes, the MasterModel definition looks like this:

public class MasterModel : IViewModel
{
   public NavigationManger Navigation { get; set; }

   public MasterModel(NavigationManager nm)
   {
      Navigation = nm;
   }

   public IViewModel SubModel { get; set; }
}

You can see that it takes the navigation manager as well as a sub model where needed. This is key: it doesn't have knowledge about the modules it will be interacting with, so it only knows about the IViewModel. We'll get more specific in a bit. The master module can hold things like settings, static lists, authentication, etc, to pass down to sub modules as needed.

Now let's get down to an actual module that will use this. Let's say I have a module called ModuleUserManager and it has a view model called UserManagerModel. It needs a token for security that is stored in the master module.

First, let's extend the ViewBase to make it easier to grab a model. We can't type the view base because we are basing our controls on UserControl, which isn't typed. We can, however, type methods. I added this method as a simple helper:

protected T _GetViewModel<T>() where T: IViewModel 
{
    MasterModel model = DataContext as MasterModel;
    return model == null ? null : (typeof(T).Equals(typeof(MasterModel)) ? model as T : model.ModuleViewModel as T); 
}

Remember, we bound the master to the shell, so the hierarchical nature of data-binding means the data context will continue to be that until I override it. We'll override it in our view, but at this level we still see the master model. The method simply casts the data context and then either returns it the master model is being requested, or access the ModuleViewModel property and returns that (also typed). This was set earlier in the call to the _ViewBaseInitialize.

Now my view can be based on ViewBase. Simply add a user control, go into the XAML, reference the namespace for the view base and then switch from UserControl to ViewBase. The XAML will look like this:

<vw:ViewBase x:Class="MyApp.ModuleUserManager.Views.UserView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"  
    xmlns:vw="clr-namespace:MyApp.Common.Base;assembly=MyApp.Common"
    >
    <Grid DataContext="{Binding ModuleViewModel}"/>
</vw:ViewBase>

In this example, we've taken the user control and exposed it as a ViewBase because the partial class must have the same base in both XAML and code behind. I've also bound the grid to the "module view model" so it has access to the local view model. In the code behind, we pass the module-specific view model to the initializer:

public partial class UserView : ViewBase
{
    public UserView()
    {
        InitializeComponent();
        _ViewBaseInitialize(new UserManagerModel());
    } 
}

Note that the master model is going to be shared. Even though I dynamically loaded the module and the view with Prism, the data context for the control itself remains bound to the "master" (shell) and therefore can reference all of the properties I've set in previous screens. My new, local view model gets bound as a property to this master view so the local properties can be accessed in the XAML. What if I have a property called Token in my master that I need to reference in my local view model? I can simply add a hook into the loaded event (so I'm sure all of the binds, etc have taken place) and then use my new helper method. I'll add this after the _ViewBaseInitialize call:

        Loaded += (o, e) =>
            {
                MasterModel master = _GetViewModel<MasterModel>();
                UserManagerModel userModel = _GetViewModel<UserManagerModel>();
                userModel.Token = master.Token; 
            };


That's it. Obviously there are more elegant ways to bind the view models together other than the code-behind, but I tend not to be the fanatic purist some others might be when it comes to simple actions and tasks that coordinate views and view models. If that task has "awareness" of an event triggered in the view and the view model, I don't see the issue with tapping into that action to glue things together.

The final thought I'll leave you with is the possibility of the sub modules being a stack. In this scenario, each view would push the view model onto the stack. Then, if you clicked the back button, the previous view could pop its view from the stack and restore the state it was in. This way the master model would help coordinate undo/redo functionality without having knowledge the specific models it collects.

Jeremy Likness

Oh wait, even better...

After posting this, I realized there was even a better way to class the base view. If I do this:

protected void _ViewBaseInitialize<T>(Action<MasterModel,T> onLoaded) where T: IViewModel, new()
{
    // must fire when loaded, as this is when it will be in the region
    // and ready to inherit the view model
    Loaded += (o, e) =>
    {
        MasterModel model = DataContext as MasterModel;
        model.Navigation.ViewChanged += new EventHandler<ViewChangedEventArgs>(nm_ViewChanged);
        
        if (typeof(T) != typeof(MasterModel))
        {
            model.ModuleViewModel = new T();
        }

        if (onLoaded != null)
        {
            onLoaded(model, model.ModuleViewModel as T);
        }
    };
}

Then I simply changed my derived view to this:

public UserView()
{
    InitializeComponent();
    _ViewBaseInitialize<UserManagerModel>((masterModel, userModel) =>
        {
            userModel.Token = masterModel.Token;
        });           
}

Even better!

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