A few weeks ago I had a problem how to combine the Silverlight Navigation Framework (now on NF) with Prism. It is a known fact that the Prism and the NF are not directly compatible. The main problem was that the Prism makes the UI composition with regions and the NF uses frames. I wanted to use the NF because it interacts with the Browser History journal.
I googled to find a good way to do this but all the solutions where somewhat limited or required some kind of hack. I was not happy with those so I dived deeper to the NF. I found out that in Silverlight 4, the navigation framework allows one to write own content loaders for the Frame. This is great because I could build my own content loader using Unity.
Prism uses Unity as a default dependency injection container. I created new content loaded that loads the views to the frame by using Unity. To be able to do this, few things are needed:
- Views needs to be registered to the Unity container before using the NF
- Uri is the fully qualified name of the view.
- Uri mapping is used to get rid of the ugly fully qualified view name
Here is the content loader code:
public class UnityNavigationLoader : INavigationContentLoader
{
private IUnityContainer _unityContainer;
public UnityNavigationLoader(IUnityContainer unityCotainer)
{
_unityContainer = unityCotainer;
}
public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState)
{
var result = new PrismContentLoaderAsyncResult(asyncState);
string typeName = GetTypeName(targetUri);
Type t = Type.GetType(typeName, false, true);
result.Result = _unityContainer.Resolve(t);
userCallback(result);
return result;
}
public bool CanLoad(Uri targetUri, Uri currentUri)
{
//We are just happy at this point that the type can be resolved
string typeName = GetTypeName(targetUri);
Type t = Type.GetType(typeName, false, true);
if (t != null)
return true;
else
return false;
}
public void CancelLoad(IAsyncResult asyncResult)
{
return;
}
public LoadResult EndLoad(IAsyncResult asyncResult)
{
return new LoadResult(((PrismContentLoaderAsyncResult)asyncResult).Result);
}
private string GetTypeName(Uri uri)
{
if (!uri.IsAbsoluteUri)
uri = new Uri(new Uri("something:///", UriKind.Absolute), uri.OriginalString);
return Uri.UnescapeDataString(uri.AbsolutePath.Substring(1));
}
}
I created the Uri mappings to the App.xaml:
<navigation:UriMapper x:Key="UriMapper">
<navigation:UriMapping Uri="Home" MappedUri="/class, assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</navigation:UriMapper>
If you are using modules (like you usually do with Prism) which contains “links”, you need to add the Uri mappings in the module initialization
UriMapper mapper = (UriMapper)Application.Current.Resources["UriMapper"];
mapper.UriMappings.Add(new UriMapping()
{
Uri = new Uri("Home2", UriKind.Relative),
MappedUri = new Uri("/" + typeof(your class).AssemblyQualifiedName, UriKind.Relative)
});
I added a Frame called “MainFrame” to the shell and assigned my own content loader to it. Remember to set the UriMapper property to the Frame
<navigation:Frame x:Name="MainFrame" Source="Home" UriMapper="{StaticResource UriMapper}"/>
And code behind
MainFrame.ContentLoader = new UnityNavigationLoader(container);
Now only thing that is missing is the HyperlinkButton that tirggers the navigation
<HyperlinkButton Content="Home" NavigateUri="Home" TargetName="MainFrame"/>
Everything is now set. This solution also support parameters that can be passed with the Uri like you would normally do. Only thing you need to make sure is that the view inherits from a NavigationPage. That way you can use the Page_Loaded event to get access to the query paramaters of the Uri. Happy coding
You can download the UnityNavigationLoader code with PrismContentLoaderAsyncResult from here.



Hi, Tero. Thanks for the post, really useful! But could you provide your PrismContentLoaderAsyncResult implementation?
Hello Anton,
Sorry for late reply, I added a link to the end of the post from where you can download the code.
-Tero
Hello Anton,
Sorry for the late reply, I added a link to the end of the post from where you can download the code.
-Tero
Hi,
Can you create a small project to demonstrate a fully working solution?
Qaiser.