Monday 31 May 2010

UriMapper not working

When using the navigation framework in Silverlight I found the URI mapping was not working. Interestingly, the Tim Heuer example on the Microsoft Silverlight web site didn’t work either.

A UriMapper something like the following was declared in App.xaml:

<Application.Resources>
    <navcore:UriMapper x:Key="UriMapper">
        <navcore:UriMapping Uri="Uri1" MappedUri="/Views/Page1.xaml" />
        <navcore:UriMapping Uri="Uri2" MappedUri="/Views/Page2.xaml" />
    </navcore:UriMapper>
</Application.Resources>

Hyperlinks were declared in the MainPage.xaml looking something like this:

<StackPanel x:Name="LeftNav" Width="150" Orientation="Vertical"/>
    <HyperlinkButton Tag="Uri1" Content="Page 1" Click="HyperlinkButton_Click" />
    <HyperlinkButton Tag="Uri2" Content="Page 2" Click="HyperlinkButton_Click" />
</StackPanel>

The navigation frame was declared in the MainPage.xaml something like this:

<navigation:Frame x:Name="Frame" />

Code in the HyperlinkButton_Click event handler looked something like this:

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    var link = sender as HyperlinkButton;
    var tag = link.Tag as string;
    Frame.Navigate(new Uri(tag, UriKind.Relative));
}

Clicking on a link produced no effect in the Silverlight application (i.e. no navigation). In IE8 a JavaScript error was reported on the page. Details of the error were along the lines of:

Message: Unhandled Error in Silverlight Application Navigation is only supported to relative URIs that are fragments, or begin with '/', or which contain ';component/'.
Parameter name: uri at System.Windows.Navigation.NavigationService.NavigateCore(Uri uri, NavigationMode mode, Boolean suppressJournalAdd)
    at System.Windows.Navigation.NavigationService.Navigate(Uri source)
    at System.Windows.Controls.Frame.Navigate(Uri source)
    at System.Windows.Controls.Frame.Frame_Loaded(Object sender, RoutedEventArgs e)
    at MS.Internal.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args)
at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName)

... snip ...

The problem turned out to be that the UriMapper declared in App.xaml was not known to the navigation frame. The solution was to map the UriMapper on the frame in the MainPage.xaml:

<navigation:Frame x:Name="Frame" UriMapper="{StaticResource UriMapper}" />