Search code examples
navigationmvvm-lightsilverlight-5.0navigation-framework

How to combine Tim Heuer navigation framework template with MVVM Light


I created new SL Application based on MVVM Light template by Laurent Bugnion. Then I created several navigation pages in /Views directory - Home.xaml,TaskPlans.xaml, Tasks.xaml and Tasks.xaml. Those pages are empty - I created only simple textblock into each page.

According to Tim Heuers template for implementing navigation framework I modified /Views/MainPage.xaml

<UserControl x:Class="Valachy.Administration.Views.MainPage"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"             
         xmlns:Helpers="clr-namespace:Valachy.Administration.Helpers" 
         xmlns:res="clr-namespace:Valachy.Administration.Resources"
         xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
         xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
         d:DesignWidth="640" d:DesignHeight="480"
         mc:Ignorable="d"             
         DataContext="{Binding Main, Source={StaticResource Locator}}">

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="../Skins/MainSkin.xaml" />
            <ResourceDictionary>
                <Helpers:ResourceWrapper x:Key="ResourceWrapper" />
                <Helpers:NotOperatorValueConverter x:Key="NotOperatorValueConverter" />
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

<Grid x:Name="LayoutRoot">
    <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
        <StackPanel Orientation="Horizontal" Width="250">
            <HyperlinkButton Click="NavigateButtonClick" Tag="Home" Content="Home" FontFamily="24"></HyperlinkButton>
            <HyperlinkButton Click="NavigateButtonClick" Tag="/Views/Tasks.xaml" Content="Tasks" FontFamily="24"></HyperlinkButton>
            <HyperlinkButton Click="NavigateButtonClick" Tag="/Views/TaskPlans.xaml" Content="Plans" FontFamily="24"></HyperlinkButton>
        </StackPanel>
    </StackPanel>
    <navigation:Frame x:Name="MainFrame" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Margin="20" Source="/Views/Home.xaml"  />
</Grid>
</UserControl>

And here is method handling hyperling click:

private void NavigateButtonClick(object sender, System.Windows.RoutedEventArgs e)
    {
        HyperlinkButton hyperlinkButton = sender as HyperlinkButton;
        if (hyperlinkButton != null)
        {
            string urlString = hyperlinkButton.Tag.ToString();                
            Uri url = new Uri(urlString,UriKind.Relative);
            MainFrame.Navigate(url);
        }
    }

I also changed /App.xaml to hide /Views/Home.xaml in address bar after # character and changed Tag attribute value in first hyperlink button in MainPage.xaml.

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         x:Class="Valachy.Administration.App"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:vm="clr-namespace:Valachy.Administration.ViewModel"
         xmlns:navcore="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"
         mc:Ignorable="d">
<Application.Resources>

    <!--Global View Model Locator-->
    <vm:ViewModelLocator x:Key="Locator"
                         d:IsDataSource="True" />
    <navcore:UriMapper x:Key="uriMapper">            
        <navcore:UriMapping Uri="Home" MappedUri="/Views/Home.xaml" />
        <navcore:UriMapping Uri="Tasks" MappedUri="/Views/Tasks.xaml" />
        <navcore:UriMapping Uri="TaskPlans" MappedUri="/Views/TaskPlans.xaml" />
    </navcore:UriMapper>
</Application.Resources>
</Application>

When I run application and provide navigation events clicking on "Tasks" and "TaskPlans" button, everything is working o.k. If I click on "Home" hyperlink button, I receive System Argument exception in iexplore.exe with message "Content for the URI cannot be loaded. The URI may be invalid."

When I change Tag content of first hyperlink button back to "/Views/Home.xaml", navigation works fine.

Can I change Tag Value somehow or there is a difference how Urimapper works in SL 5?

Thank you for any advice, Rudolf.


Solution

  • Check out Laurent's talk at Mix "deep dive MVVM"

    in this talk he speaks about how to Navigate with MVVM. He suggest a navigation Service... This talk is really a good watch for some advanved MVVM techniques...

    http://channel9.msdn.com/Events/MIX/MIX11/OPN03