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!





April 5th, 2010 at 16:48
[...] This post was mentioned on Twitter by Larry King. Larry King said: Silverlight 4, MEF and MVVM: MEFModules, Dynamic XAP Loading and … http://bit.ly/dz5c2z #SL #RIA [...]
April 6th, 2010 at 06:37
Social comments and analytics for this post…
This post was mentioned on Twitter by davidezordan: blogged: #Silverlight 4, #MEF and #MVVM: MEFModules, Dynamic XAP Loading and Navigation – http://bit.ly/ahaS1U #in #fb…
April 20th, 2010 at 19:39
Thanks. This is what i have been looking for, for quite a long time.It will come in handy immediately.
May 7th, 2010 at 22:50
How can this be modified to reuse the MEFModuleContainer and load different xap’s. I would like to use the same container for different imports. Thanks.
May 9th, 2010 at 20:28
Hi Bob,
one solution: you can decorate the exports in the external xaps with metadata, import the user controls in a collection and display them in the module container.
June 4th, 2010 at 14:21
This was very helpful and very clear. Thank You.
June 4th, 2010 at 15:20
Thank you Michael
, glad you like it!
June 17th, 2010 at 05:06
I like it. My only question is the use of PRISM to do the messaging, and only because it adds so much to the size compared to simpler messaging solutions(MVVM Light).
Other than that, this is really useful… Thanks!
June 18th, 2010 at 02:24
David, I reviewed how I do this for Navigation apps, and it’s fairly close except for one thing.
I use the INavigationContentLoader interface to detect when the page loads, and instead of using the AddXap method to detect if the XAP is loaded, I set a “Persist” flag, and load the page from a cache.
The value of this for me is that I have the option of persisting the page or not. In your case, the page Initializes every time, and sometimes you want to remember what the user was doing the last time they were there.
That way I never download again, and I never initialize the page more than once, unless the persist flag is set to false.
June 18th, 2010 at 14:34
Hi Fallon,
thank you for the comment, great suggestion
July 26th, 2010 at 00:19
[...] create a new module using WCF RIA Services and dynamically load this it inside the “MEF module container” described in the previous post; [...]