You implement application navigation in a Silverlight application by using the Frame and Page controls. Page controls represent discrete sections of content. The frame acts as a container for page controls, and facilitates navigation to pages. At any one time, the frame displays the content of a single page. You change the page that is displayed within the frame by navigating, either programmatically or through user action, to a new page.
You can design the root visual of your Silverlight application to contain a combination of navigable content plus permanent user-interface (UI) components, such as headers, footers, and navigation sidebars. When you create a new project by using the Silverlight Navigation Application template, the template generates a XAML file that contains permanent UI components and a frame for navigable content.
The following example shows a simple frame that exists inside of a UserControl control named MainPage. You could add other UI components to LayoutRoot before or after ContentFrame. The Source property is set to /Views/Home.xaml which means that by default the page displayed in the frame is the page located at /Views/Home.xaml.
<!-- NOTE:
By convention, the sdk prefix indicates a URI-based XAML namespace declaration
for Silverlight SDK client libraries. This namespace declaration is valid for
Silverlight 4 only. In Silverlight 3, you must use individual XAML namespace
declarations for each CLR assembly and namespace combination outside the scope
of the default Silverlight XAML namespace. For more information, see the help
topic "Prefixes and Mappings for Silverlight Libraries".
-->
<UserControl x:Class="SilverlightApplication.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
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"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<sdk:Frame x:Name="ContentFrame" Source="/Views/Home.xaml">
</sdk:Frame>
</Grid>
</UserControl>
You can add new pages to your application by using the Add New Item dialog box and selecting Silverlight Page. The Silverlight Navigation Application template in Visual Studio creates a folder named Views that contains pages. You can add pages to this folder, or you can add pages anywhere in your application that is most appropriate.
Creating User-Friendly URIs
Within a frame, you can specify that a certain URI pattern maps to a particular page. URI mapping enables you to create URIs that are descriptive of the user action instead of a path to a file. For example, you can specify that any request for /Home is actually a request for the file at /Views/Home.xaml. Any request that does not match one of the defined patterns is handled as a regular URI request and is not mapped to a different page. The following table shows examples of URI mapping definitions and how example requests are resolved.
URI Mapping Definition | Example of Matching URI | Resolved URI |
|---|
Uri = "/Home" MappedUri = "/Views/Home.xaml" | /Home | /Views/Home.xaml |
Uri = "/{page}" MappedUri = "/Views/{page}Page.xaml" | /About | /Views/AboutPage.xaml |
Uri = "/Product/{category}" MappedUri = "/ContosoShop/Product.xaml?category={category}" | /Product/bikes | /ContosoShop/Product.xaml?category=bikes |
Uri = "/{reporttype}/{month}/{format}" (in XAML) MappedUri = "/Views/Reports/{reporttype}.xaml?time={month}&show={format}" (in Visual Basic or C#) MappedUri = "/Views/Reports/{reporttype}.xaml?time={month}&show={format}" | /Sales/June/Short | /Views/Reports/Sales.xaml?time=June&show=Short |
You add URI mapping to a frame by defining an instance of the UriMapper class (or a custom class that derives from UriMapperBase class) and any number of UriMapping instances. The pattern you specify does not have to be the exact URI to match against the requested URI. The pattern can include placeholder segments in the URI that will match any value in that segment. You specify a placeholder segment by enclosing the name of the segment with curly braces ( { and } ). The placeholder segment acts as a variable when mapping to the URI. Any value that is not enclosed in curly braces represents a literal value that must be present for the URI to match the pattern. The following example shows URI patterns that include placeholder values.
<sdk:Frame
x:Name="ContentFrame"
Style="{StaticResource ContentFrameStyle}"
Source="/Home"
Navigated="ContentFrame_Navigated"
NavigationFailed="ContentFrame_NavigationFailed">
<sdk:Frame.UriMapper>
<sdk:UriMapper>
<sdk:UriMapping
Uri="/ProductDetail/{productid}"
MappedUri="/Views/ProductDetail.xaml?ProductId={productid}"/>
<sdk:UriMapping
Uri="/Reports/{type}/{selection}"
MappedUri="/Views/ReportsPage.xaml?type={type}&selection={selection}"/>
<sdk:UriMapping
Uri="/{pageName}"
MappedUri="/Views/{pageName}.xaml"/>
</sdk:UriMapper>
</sdk:Frame.UriMapper>
</sdk:Frame>
The URI request is mapped to the first pattern that matches the request. Therefore, add your URI mapping instances from most specific to most general. For example, the following definitions are correctly ordered from a specific literal value to a general placeholder value. A request for /SalesReport would map to /Views/Reports/Sales.xaml.
<sdk:Frame x:Name="ContentFrame" Source="/Home">
<sdk:Frame.UriMapper>
<sdk:UriMapper>
<sdk:UriMapping Uri="/SalesReport" MappedUri="/Views/Reports/Sales.xaml"/>
<sdk:UriMapping Uri="/{page}" MappedUri="/Views/{page}Page.xaml"/>
</sdk:UriMapper>
</sdk:Frame.UriMapper>
</sdk:Frame>
However, if you reverse the order of the URI mapping definitions, a request for /SalesReport would not map to /Views/Reports/Sales.xaml. Instead, the first definition /{page} would match every single segment request including /SalesReport. The request would map to /Views/SalesReportPage.xaml.
Facilitating Navigation to Pages
The Frame class provides methods and properties to navigate to pages. You set the Source property to the URI for the page to display, or you call the Navigate method and pass the URI for the page as a parameter. You can also use the GoBack and GoForward methods to navigate back or forward in the navigation history.
You can use the HyperlinkButton control to enable users to navigate to pages within the application. When the HyperlinkButton control is inside of a Silverlight page that is hosted in a frame, you set the NavigateUri property to a URI that maps to a page and you do not set the TargetName property. The hosting frame will navigate to the requested page. The following example shows a page with a HyperlinkButton that navigates to another page in the application.
<!-- NOTE:
By convention, the sdk prefix indicates a URI-based XAML namespace declaration
for Silverlight SDK client libraries. This namespace declaration is valid for
Silverlight 4 only. In Silverlight 3, you must use individual XAML namespace
declarations for each CLR assembly and namespace combination outside the scope
of the default Silverlight XAML namespace. For more information, see the help
topic "Prefixes and Mappings for Silverlight Libraries".
-->
<sdk:Page x:Class="SilverlightApplication.Home"
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
Title="Home">
<Grid x:Name="LayoutRoot">
<HyperlinkButton NavigateUri="/About" Content="About"></HyperlinkButton>
</Grid>
</sdk:Page>
When the HyperlinkButton control resides outside of the frame, you can enable navigation to resources within the frame by setting the NavigateUri property to a URI that maps to a page and setting the TargetName property to the name of the frame. The following example shows a frame and two HyperlinkButton controls that reside outside of the frame. The HyperlinkButton controls facilitate navigation to pages that are displayed within the frame. The TargetName property on both HyperlinkButton controls is set to ContentFrame, which is the name assigned to the frame.
<Grid x:Name="LayoutRoot">
<Border>
<sdk:Frame x:Name="ContentFrame" Source="/Home">
<sdk:Frame.UriMapper>
<sdk:UriMapper>
<sdk:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
</sdk:UriMapper>
</sdk:Frame.UriMapper>
</sdk:Frame>
</Border>
<Grid>
<Border>
<StackPanel>
<HyperlinkButton NavigateUri="/Home" TargetName="ContentFrame" Content="home"/>
<HyperlinkButton NavigateUri="/About" TargetName="ContentFrame" Content="about"/>
</StackPanel>
</Border>
</Grid>
</Grid>
When you need to programmatically initiate a navigation request from a page, you must first get the NavigationService object that is used by the host frame. The NavigationService class provides members, such as GoBack, GoForward, and Source, for navigating to pages. For an example that shows a Silverlight page utilizing the NavigationService object, see the Application Navigation Example later in this topic.