Migrating Composite Application Guidance (Prism-v2) to XBAP

I’ve seen that there are quite a few questions on how to use Composite Application Guidance for WPF and Silverlight (a.k.a Prism) with XBAP applications on the discussion list, so I’ll try show you in this post how to migrate the HelloWorld demo (included with CAL) to XBAP. If you are in a hurry, you can skip directly to the Solution.

Problem

The main issue is that XBAP applications rely on WPF framework to create the NavigationWindows that will be holding XBAP pages and CAL needs to create the main window on the Bootstrapper (creating instances of NavigationWindows is not allowed in PartialTrust applications).

The first thing that you will do to convert your WPF application into an XBAP application is changing <Window> for <Page> in you XAMLs. In most scenarios that is practically all you have to do because WPF framework is intelligent enough to create the right environment for the application: If you are using Windows, it just creates a new instance of a window and calls it’s Show method (like you usually do in the CAL’s Bootstrapper). But if you are using Pages, it needs to host pages in NavigationWindows or the Browser.

But, if you are using CAL after changing your Windows for Pages, you will end up commenting the call to the Show Method (pages don’t have a Show method) and setting the starupURI of the application. And that’ were the root of the problem lies: WPF creates an instance of a Page and you are creating another instance in the Bootstrapper. That will mess up things and you will end up loosing references to the CAL’s regions and contentControls.

Solution

We will start with the HelloWorldDemo.Desktop Quickstart included in Prism v2.

Set the shell as the startup page of the application. To do that, open the App.xml file and add StartupUri=”Shell.xaml” to the <Application> element.<Application x:Class=“HelloWorld.App”xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”StartupUri=“Shell.xaml“>
<Application.Resources>
</Application.Resources>
</Application>

In the App.xaml code behind (App.xaml.cs) remove the OnStartup method. We will add the BootStrapper initialization afterwards.

In the Shell.xaml file change the <Window> element for a <Page> element. You should end up with the Shell.xaml code as follows:<Page x:Class=“HelloWorld.Shell”xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”xmlns:cal=“http://www.codeplex.com/CompositeWPF”Title=“Hello World” Height=“300” Width=“300“>
<ItemsControlName=“MainRegion” /></Page>

In the Shell.cs make Shell inherit from Page instead of Window. Ej: public partial class Shell : Page

To avoid creating a new instance of the shell, get the one created during the Application startup. A good place to do that is the Shell constructor.