Silverlight 4, MEF and MVVM: MEFModules, Dynamic XAP Loading and Navigation Applications
In the last example I’ve implemented a new “MEF Module” organized with a MVVM approach and using Prism Event Aggregator to exchange messages.
This new module could be used to partititon the application in several XAPs composed dynamically at run-time using MEF, the new DeploymentCatalog and the Navigation features available in Silverlight.
To start I’ve created a new “Silverlight Navigation Application” which produces a complete application with ready-to-use navigation and localization.
Then I’ve inserted a new “Silverlight User Control” inside the “Views” folder and named it “MEFModuleContainer“: this one is called by the navigation framework and is responsible to load dynamically the module using the MEF “DeploymentCatalog“.
This is the XAML of the container:
<StackPanel x:Name="ContentStackPanel">
<TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"
Text="MEF Module container"/>
<TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}"
Text="MEF content"/>
<ItemsControl x:Name="content"/>
</StackPanel>
Our “MEF Module” is hosted in a “ItemsControl” using the “Items” property:
public MEFModuleContainer()
{
InitializeComponent();
CompositionInitializer.SatisfyImports(this);
CatalogService.AddXap("MEFModule.xap");
}
[Import]
public IDeploymentCatalogService CatalogService { get; set; }
[ImportMany(AllowRecomposition = true)]
public Lazy<UserControl>[] MEFModuleList { get; set; }
#region IPartImportsSatisfiedNotification Members
public void OnImportsSatisfied()
{
MEFModuleList.ToList()
.ForEach(module=>
content.Items.Add(module.Value)
);
}
#endregion
In order to use the DeploymentCatalog, it’s necessary to define an interface “IDeploymentCatalogService“ (read this post by Glenn Block for more information about it):
public interface IDeploymentCatalogService
{
void AddXap(string uri, Action<AsyncCompletedEventArgs> completedAction = null);
void RemoveXap(string uri);
}
and implement it in the class “DeploymentCatalogService“:
[Export(typeof(IDeploymentCatalogService))]
public class DeploymentCatalogService : IDeploymentCatalogService
{
private static AggregateCatalog _aggregateCatalog;
Dictionary<string, DeploymentCatalog> _catalogs;
public DeploymentCatalogService()
{
_catalogs = new Dictionary<string, DeploymentCatalog>();
}
public static void Initialize()
{
_aggregateCatalog = new AggregateCatalog();
_aggregateCatalog.Catalogs.Add(new DeploymentCatalog());
CompositionHost.Initialize(_aggregateCatalog);
}
public void AddXap(string uri, Action<AsyncCompletedEventArgs> completedAction = null )
{
DeploymentCatalog catalog;
if (!_catalogs.TryGetValue(uri, out catalog))
{
catalog = new DeploymentCatalog(uri);
if (completedAction != null)
catalog.DownloadCompleted += (s, e) => completedAction(e);
else
catalog.DownloadCompleted += catalog_DownloadCompleted;
catalog.DownloadAsync();
_catalogs[uri] = catalog;
_aggregateCatalog.Catalogs.Add(catalog);
}
}
void catalog_DownloadCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
throw e.Error;
}
public void RemoveXap(string uri)
{
DeploymentCatalog catalog;
if (_catalogs.TryGetValue(uri, out catalog))
{
_aggregateCatalog.Catalogs.Remove(catalog);
}
}
}
The DeploymentCatalogService is initialized during the Application startup in this way:
private void Application_Startup(object sender, StartupEventArgs e)
{
//Initialize the DeploymentCatalogService for MEF
DeploymentCatalogService.Initialize();
this.RootVisual = new MainPage();
}
When the user clicks on the Navigation bar, the container is loaded and filled with the content of the external XAP, all managed by MEF:
So we have a Navigation application which can dynamically load external “MEFModules” organized with a MVVM approach, contained in external XAPs and using an Event Aggregator to exchange messages, all managed by MEF.
This application can be easily extended inserting WCF RIA Services and/or Blend sample data for the design mode.
As usually the sample code is available for download here and will be soon available in the CodePlex project “MEF MVVM” – http://mefmvvm.codeplex.com.
Happy Silverlighting!



