In this section, you'll create a new view and add a link to it in the menu (part 1). You will then create another view that you pass data to as a query string parameter (part 2). Finally, you will map a custom URI, demonstrating how you can make the URI “friendlier” in the address bar (part 3).
In this first exercise, let's create a new view and add a link to it.
ProductListView.xaml
, using the Silverlight Page item template.
MainPage.xaml
, and search for a StackPanel control named LinksStackPanel
:
<StackPanel x:Name="LinksStackPanel"
Style="{StaticResource LinksStackPanelStyle}">
<HyperlinkButton x:Name="Link1" Style="{StaticResource LinkStyle}"
NavigateUri="/Home" TargetName="ContentFrame"
Content="{Binding Path=Strings.HomePageTitle,
Source={StaticResource ApplicationResources}}"/>
<Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/>
<HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}"
NavigateUri="/About" TargetName="ContentFrame"
Content="{Binding Path=Strings.AboutPageTitle,
Source={StaticResource ApplicationResources}}"/>
</StackPanel>
Divider2
, and name the new HyperlinkButton ProductsLink
. The squiggly blue underline both these controls have in the XAML editor, indicating they have errors, should go away. Set the HyperlinkButton's NavigateUri
property to /ProductListView
(the name of the new view, but without the .xaml
extension), and set its Content
property to Products
.
Note Silverlight's Business Application template uses resources to define the text displayed by the HyperlinkButton controls, hence the bindings used by their Content
properties. This is a great strategy when your application is to be multilingual. However, for the purpose of this workshop, we'll keep things simple and simply hard-code their text.
<StackPanel x:Name="LinksStackPanel"
Style="{StaticResource LinksStackPanelStyle}">
<HyperlinkButton x:Name="Link1" Style="{StaticResource LinkStyle}"
NavigateUri="/Home" TargetName="ContentFrame"
Content="{Binding Path=Strings.HomePageTitle,
Source={StaticResource ApplicationResources}}"/>
<Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/>
<HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}"
NavigateUri="/About" TargetName="ContentFrame"
Content="{Binding Path=Strings.AboutPageTitle,
Source={StaticResource ApplicationResources}}"/>
<Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/>
<HyperlinkButton x:Name="ProductsLink" Style="{StaticResource LinkStyle}"
NavigateUri="/ProductListView" TargetName="ContentFrame"
Content="Products"/>
</StackPanel>
Let's add a view that we'll pass some data to using a query string parameter, and I'll demonstrate accessing the value from that view.
ProductDetailsView.xaml
, using the Silverlight Page item template (as demonstrated in part 1).LayoutRoot
Grid), named DisplayValueTextBlock
:
<Grid x:Name="LayoutRoot">
<TextBlock Name="DisplayValueTextBlock" Width="100" Height="25" />
</Grid>
ProductListView
view and display that in the DisplayValueTextBlock
TextBlock control. Go back to the ProductListView
view, and add the following content in bold to the LayoutRoot Grid control in that view:
<Grid x:Name="LayoutRoot">
<StackPanel Height="25" Orientation="Horizontal" Width="155">
<TextBox Name="ValueField" Width="100" />
<Button Width="50" Content="Go" Margin="5,0,0,0" />
</StackPanel>
</Grid>
ProductDetailsView
view in code and pass it the text entered into the ValueField
text box in its query string, as a parameter named Value
. We'll use the NavigationService
property, inherited from the Page
class, for this purpose. Add this code to the event handler:
Uri uri = new Uri("/ProductDetailsView?Value=" + ValueField.Text, UriKind.Relative);
NavigationService.Navigate(uri);
ProductDetailsView
view. Add the following property, simplifying safe access to the Value
query string parameter, to its code-behind:
private string ParamValue
{
get
{
string paramValue = "";
const string paramName = "Value";
if (NavigationContext.QueryString.ContainsKey(paramName))
paramValue = NavigationContext.QueryString[paramName];
return paramValue;
}
}
OnNavigatedTo
method. You'll find this method is already defined in the view's code-behind.
DisplayValueTextBlock.Text = ParamValue;
ProductListView
view, via the menu, and enter some text in the text box. When you click the button, the ProductDetailsView
view is navigated to and displays the value that you entered in the text box in the previous page.Instead of navigating to this (somewhat ungainly) URI:
/ProductDetailsView?Value=SomeValue
Let's create a custom URI mapping, so we can navigate to the following URI instead:
/ProductDetails/SomeValue
So far, we've been making use of one of the default mappings, which has allowed us to exclude the Views/
and the .xaml
portions of a view's name when navigating to it. Let's take things to the next level and create our own mapping.
MainPage.xaml
, and then find its UriMapper
property:
<navigation:Frame.UriMapper>
<uriMapper:UriMapper>
<uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
<uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
</uriMapper:UriMapper>
</navigation:Frame.UriMapper>
<uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
and extend it to omit the View
part of the view's name and to define a token to automatically assign the “second part” of the URI as the value of the Value
query string parameter, like so:
<uriMapper:UriMapping Uri="/{pageName}/{value}"
MappedUri="/Views/{pageName}.xaml?Value={value}"/>
ProductListView.xaml
view. In the Button control's event handler, change the line defining the URI to make use of our new mapping:
Uri uri = new Uri("/ProductDetailsView/ " + ValueField.Text, UriKind.Relative);
ProductDetailsView
view, the navigation should still work correctly and the value entered into the ProductListView
view should still appear. As a further exercise, take a look at the URI in the browser's address bar, and modify the Value
part of the URI. You will find that the ProductDetailsView
view displays the value you entered in the address bar.