Prism 4 Region Navigation with Silverlight Frame Navigation and Unity

I have had several requests to demonstrate how to use Unity with Prism 4 Region Navigation and the Silverlight Frame Navigation framework.

The primary purpose of this blog post is to provide an example of using Unity for dependency resolution when writing a Silverlight application that also uses Prism 4 Region Navigation and the Silverlight Frame Navigation framework.

Required Reading

If you have not yet read these blog post please do so now.

These blog posts provide critical foundational information that will not be repeat in this blog post.

Example Code

This blog post is a direct port of the code from the above Cancelling a Navigation Request using Prism v4 Region Navigation with Silverlight Frame Navigation post that uses MEF for dependency resolution.  That code has been ported to use Unity instead. 

The code in this blog post includes the prompt for navigation cancelling feature that gets called when navigating away from the inventory item page. This prompt demonstrates implementing the IConfirmNavigationRequest.ConfirmNavigationRequest method in Silverlight when the Silverlight Frame Navigation framework is also being used.

Configuring the Unity Container

When using Unity with Prism 4 Region Navigation in either Silverlight or WPF applications, the Unity container needs to be configured in a special way.  This is required because of the way the Prism Region Navigation API requests objects from the Unity container.

The below text is taken from the “Basic Region Navigation” section of on Prism 4 MSDN documentation page: https://msdn.microsoft.com/en-us/library/gg430861(v=PandP.40).aspx

ConfiguringUnity

The following code snippet is from the Bootstrapper.cs file in the, “ThePhoneCompany” project.  This shows how to properly register views with Unity that will be navigated to using the Prism 4 Navigation API.  The views are registered as type Object and then the type full name is used to name the view in the Unity container.

Notice how I have chosen to use the type full name instead of the type name.  Using the type full name prevents name collisions across different modules and makes navigating across modules very easy.

 protected override void ConfigureContainer() {
    base.ConfigureContainer();

    Container
        .RegisterType<Object, AboutView>(typeof(AboutView).FullName)
        .RegisterType<Object, HomeView>(typeof(HomeView).FullName);
}

The below UriMapper XAML is from the ShellView.  You can see how the above view type full names map to the below Urls. 

Example:  User navigates to /#/HomeView, the Region Navigation API will request the “ThePhoneCompany.Views.HomeView” named object from the Unity Container and begin the navigation process. 

Example: User navigates to /#/Inventory/ItemView/1009, the Region Navigation API will request the “ThePhoneCompany.Inventory.Views.ItemView” named object from the Unity Container and begin the navigation process.

 <navigation:Frame.UriMapper>
    <uriMapper:UriMapper>
                        
        <!--Default applicaiton mapper-->
        <uriMapper:UriMapping Uri="" MappedUri="/ThePhoneCompany.Views.HomeView"/>
                       
        <!--Used to add a new record-->
        <uriMapper:UriMapping Uri="/{moduleName}/{pageName}/add" MappedUri="ThePhoneCompany.{moduleName}.Views.{pageName}?key=0"/>
                        
        <!--Used to edit a record-->
        <uriMapper:UriMapping Uri="/{moduleName}/{pageName}/{key}" MappedUri="ThePhoneCompany.{moduleName}.Views.{pageName}?key={key}"/>

        <!--Used to view a page-->
        <uriMapper:UriMapping Uri="/{moduleName}/{pageName}" MappedUri="ThePhoneCompany.{moduleName}.Views.{pageName}"/>
                        
        <!--Used to navigate to a page in the Shell-->
        <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/ThePhoneCompany.Views.{pageName}"/>

    </uriMapper:UriMapper>
</navigation:Frame.UriMapper>

The below code snippet is from the InventoryModule.cs file.  Notice again how the views are registered in the Unity Container as type Object and named using the type full name.

 public class InventoryModule : IModule {

    public InventoryModule(IUnityContainer container) {
        container
            .RegisterType<InventoryViewModel>()
            .RegisterType<ItemViewModel>()
            .RegisterType<CategoryViewModel>()
            .RegisterType<Object, InventoryView>(typeof (InventoryView).FullName)
            .RegisterType<Object, ItemView>(typeof (ItemView).FullName)
            .RegisterType<Object, CategoryView>(typeof (CategoryView).FullName);
    }

    public void Initialize() {
           
    }
}

Running the Sample Code

Requirements: you must download Prism 4 or later and run the RegisterPrismBinaries.bat batch file. The Prism v4 Readme covers this file in detail. If you do not want to run this batch file, you'll need to remove and re-add the references to the Prism assemblies.

The attached code uses Unity for dependency resolution.  This code also demonstrates cancelling a navigation request. To see this in action, run the application, select Inventory in the menu bar, select an inventory item to edit, then press the Close button on the inventory item form. A MessageBox will prompt you to continue the navigation or cancel it.

Comments

Microsoft values your opinion about our products, guidance, documentation and samples.

Thank you for your feedback and have a great day,

Karl Shifflett

SLPrismNavigationUnity.zip