Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

Migrate from Basic to MVVM and MEF Composable Patterns for a Silverlight Application - Part 3

, 3 May 2012 CPOL
The article series shows how to upgrade a Silverlight application having basic patterns to the MVVM and MEF composable patterns with easy approaches and detailed coding explanations.
MigrateToMvvmMef-Part1_Src.zip
MigrateToMvvmMef-Part1_Src
ProductApp.Common
Bin
Release
Constants
ModuleServices
obj
ProductApp.Common.csproj.user
Properties
ProductApp.Main
Assets
Bin
Release
obj
ProductApp.Main.csproj.user
Properties
Views
ProductApp.suo
ProductApp.Views
Assets
Bin
Release
obj
ProductApp.Views.csproj.user
Properties
ProductApp.Web
bin
ClientBin
obj
ProductApp.Web.csproj.user
Properties
ProductRiaLib
ProductRiaLib.Web
App_Data
bin
Debug
EntityFramework.dll
Microsoft.ServiceModel.DomainServices.EntityFramework.dll
Release
Models
obj
ProductRiaLib.Web.csproj.user
Properties
Services
Bin
Release
obj
ProductRiaLib.csproj.user
Properties
MigrateToMvvmMef-Part2_Src.zip
MigrateToMvvmMef-Part2_Src
ProductApp.Common
Bin
Release
Constants
EventArguments
Models
ModuleServices
obj
ProductApp.Common.csproj.user
Properties
ProductApp.Main
Assets
Bin
Release
obj
ProductApp.Main.csproj.user
Properties
ViewModels
Views
ProductApp.Models
Bin
Release
obj
ProductApp.Models.csproj.user
Properties
ProductApp.suo
ProductApp.ViewModels
Bin
Release
obj
ProductApp.ViewModels.csproj.user
Properties
ProductApp.Views
Assets
Bin
Release
obj
ProductApp.Views.csproj.user
Properties
ProductApp.Web
bin
ClientBin
obj
ProductApp.Web.csproj.user
Properties
ProductRiaLib
ProductRiaLib.Web
App_Data
bin
Debug
EntityFramework.dll
Microsoft.ServiceModel.DomainServices.EntityFramework.dll
Release
Models
obj
ProductRiaLib.Web.csproj.user
Properties
Services
Bin
Release
obj
ProductRiaLib.csproj.user
Properties
_Assemblies
GalaSoft.MvvmLight.SL5.dll
System.Windows.Interactivity.dll
MigrateToMvvmMef-Part3_Src.zip
MigrateToMvvmMef-Part3_Src
AnotherXap.Models
AnotherXap.Models.csproj.user
Bin
Release
obj
Properties
AnotherXap.ViewModels
AnotherXap.ViewModels.csproj.user
Bin
Release
obj
Properties
AnotherXap.Views
AnotherXap.Views.csproj.user
Assets
Bin
Release
obj
Properties
ProductApp.Common
Bin
Release
Constants
EventArguments
Models
ModuleServices
obj
ProductApp.Common.csproj.user
Properties
SaveState
ProductApp.Main
Assets
Bin
Release
Models
obj
ProductApp.Main.csproj.user
Properties
ViewModels
Views
ProductApp.Models
Bin
Release
obj
ProductApp.Models.csproj.user
Properties
ProductApp.suo
ProductApp.ViewModels
Bin
Release
obj
ProductApp.ViewModels.csproj.user
Properties
ProductApp.Views
Assets
Bin
Release
obj
ProductApp.Views.csproj.user
Properties
ProductApp.Web
bin
ClientBin
obj
ProductApp.Web.csproj.user
Properties
ProductRiaLib
ProductRiaLib.Web
App_Data
bin
Debug
EntityFramework.dll
Microsoft.ServiceModel.DomainServices.EntityFramework.dll
Release
Models
obj
ProductRiaLib.Web.csproj.user
Properties
Services
Bin
Release
obj
ProductRiaLib.csproj.user
Properties
_Assemblies
GalaSoft.MvvmLight.SL5.dll
System.Windows.Interactivity.dll
using System;
using System.Linq;
using System.Windows.Controls;
using System.ComponentModel;
using System.ComponentModel.Composition;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using ProductApp.Common;

namespace ProductApp.Main.ViewModels
{
    [Export(typeof(IModule)), ExportMetadata(MetadataKeys.Name, ModuleID.MainPageViewModel)]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class MainPageViewModel : ViewModelBase, IModule
    {
        private ModuleCatalogService _catalogService = ModuleCatalogService.Instance;
        private string _currentViewText = string.Empty;
        private StateCacheList<StateCache> _mainStateList;

        public MainPageViewModel()
        {
            // For saving module state info
            Messenger.Default.Register(this, MessageToken.PutStateMessage,
                                       new Action<StateCacheList<StateCache>>(OnPutStateMessage));
            _mainStateList = new StateCacheList<StateCache>();

            // For receiving state info
            Messenger.Default.Register<NotificationMessageAction<StateCacheList<StateCache>>>
                       (this, MessageToken.GetStateMessage, message => OnGetStateMessage(message));
        }

        // Get cached state data and set loading property accordingly
        private void OnPutStateMessage(StateCacheList<StateCache> stateList)
        {
            if (stateList != null)
            {
                // Remove all previous items for the calling module
                if (_mainStateList != null)
                {
                    _mainStateList.RemoveAll(m => m.ModuleID == stateList[0].ModuleID);
                }

                // Add the state list to main list
                _mainStateList.AddRange(stateList);

                stateList = null;
            }
        }

        private void OnGetStateMessage(NotificationMessageAction<StateCacheList<StateCache>> message)
        {
            if (message != null)
            {
                // Retrieve the list for the requester
                StateCacheList<StateCache> stateList = new StateCacheList<StateCache>();
                stateList.AddRange(_mainStateList.Where(w => w.ModuleID == message.Notification));

                if (stateList.Count > 0)
                {
                    // Send the state list back
                    message.Execute(stateList);

                    stateList = null;
                }
            }
        }

        // Defined with string type to pass the command parameter
        private RelayCommand<string> _loadModuleCommand;
        //
        public RelayCommand<string> LoadModuleCommand
        {
            get
            {
                if (_loadModuleCommand == null)
                {
                    // Parameter 1: define a delegate method to be executed
                    // Parameter 2: the delegate function CanExedute
                    // with one-in(object) and one-out(bool) parameters
                    // to make the command enabled or disabled
                    _loadModuleCommand = new RelayCommand<string>(
                                  OnLoadModuleCommand,
                                  moduleId => moduleId != null);
                }
                return _loadModuleCommand;
            }
        }
        //
        private void OnLoadModuleCommand(String moduleId)
        {
            string xapUri;
            try
            {
                if (_currentViewText != moduleId)
                {
                    // For loading Xap or View
                    switch (moduleId)
                    {
                        // Load ProductApp.Xap on-demand
                        case ModuleID.ProductListView:
                            xapUri = "/ClientBin/ProductApp.Views.xap";
                            _catalogService.AddXap(xapUri, arg => ProductApp_OnXapDownloadCompleted(arg));
                            break;
                        
                        // Send message back to ManiPageView code-behind to load AnotherScreenView
                        case ModuleID.AnotherScreenView:
                            Messenger.Default.Send(ModuleID.AnotherScreenView, MessageToken.LoadScreenMessage);
                            _currentViewText = ModuleID.AnotherScreenView;
                            break;

                        // Load AnotherXap on-demand
                        case ModuleID.AnotherXapView:
                            xapUri = "/ClientBin/AnotherXap.Views.xap";
                            _catalogService.AddXap(xapUri, arg => AnotherXap_OnXapDownloadCompleted(arg));
                            break;
                        
                        default:
                            throw new NotImplementedException();
                    }
                }
            }
            catch (Exception ex)
            {
                // Pass error object to View code-behind
                Messenger.Default.Send(ex, MessageToken.RaiseErrorMessage);
            }
        }

        private void ProductApp_OnXapDownloadCompleted(AsyncCompletedEventArgs e)
        {
            // Send message back to View code-behind to load ProductList View
            Messenger.Default.Send(ModuleID.ProductListView, MessageToken.LoadScreenMessage);

            // Cache for check repeat commands later
            _currentViewText = ModuleID.ProductListView;
        }

        private void AnotherXap_OnXapDownloadCompleted(AsyncCompletedEventArgs e)
        {
            // Send message back to View code-behind to load AnotherXap View
            Messenger.Default.Send(ModuleID.AnotherXapView, MessageToken.LoadScreenMessage);

            _currentViewText = ModuleID.AnotherXapView;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Shenwei Liu

United States United States
Shenwei is a software developer and architect, and has been working on business applications using Microsoft and Oracle technologies since 1996. He obtained Microsoft Certified Systems Engineer (MCSE) in 1998 and Microsoft Certified Solution Developer (MCSD) in 1999. He has experience in ASP.NET, C#, Visual Basic, Windows and Web Services, Silverlight, WPF, JavaScript/AJAX, HTML, SQL Server, and Oracle.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141216.1 | Last Updated 3 May 2012
Article Copyright 2012 by Shenwei Liu
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid