Beginning Silverlight 4 in C#-导航

在Silverlight里,导航框架允许开发者在Silverlight应用程序里实现一种方式来跳转到不同的页面,就像网站上的不同页面一样。这个框架也允许开发者创建历史使其与浏览器结合,使用户能使用浏览器的向前和向后导航。

Frame和Page对象

导航框架的两个主要对象是Frame和Page对象。Frame与ASP.NET母版页中的ContentPlaceHolder非常相似,是在一个页面放置不同views的地方。

 

image

练习:创建一个导航Silverlight应用程序

在这个练习里,会创建一个简单的应用程序包含两个超链接按钮和一个Frame。点击超链接会加载两个页面中的一个到Frame。Lets Go。

  1. 使用VS2010创建一个名为NavAppFromScratch的Silverlight应用程序。
  2. 打开MainPage.xaml,在Grid里,添加ShowGridLines="True"。定义Grid的单元格和两个超链接:
    <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <HyperlinkButton Content="View 1" Click="LinkClick" Padding="5" />
            <HyperlinkButton Content="View 2" Click="LinkClick" Padding="5" />
        </StackPanel>
    </Grid>
  3. 下一步是添加导航框架到项目。首先添加System.Windows.Controls.Navigation.dll的引用
  4. 现在添加导航对象到项目中。需要在UserControl中手动添加System.Windows.Controls.Navigation到xml命名空间里。
    <UserControl x:Class="NavAppFromScratch.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:nav="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
    
  5. 添加一个Frame到最底的Grid的单元格里,命名为ContentFrame。代码如下:
    <nav:Frame x:Name="ContentFrame" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
         Margin="10" Grid.Row="1" BorderThickness="2" BorderBrush="Black"/>
  6. 在NavAppFromScratch项目里新建两个Silverlight页,名为Page1.xaml和Page2.xaml。分别代码如下:
    <Grid x:Name="LayoutRoot">
        <TextBlock Text="View 1" FontSize="60" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
    
    <Grid x:Name="LayoutRoot">
        <TextBlock Text="View 2" FontSize="60" Foreground="Blue" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
  7. 现在要做的是点击按钮是加载页面到Frame。可以通过设置超链接按钮的Tag属性来定义要页面的源文件名。
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
        <HyperlinkButton Content="View 1" Click="LinkClick" Tag="/Page1.xaml" Padding="5" />
        <HyperlinkButton Content="View 2" Click="LinkClick" Tag="/Page2.xaml" Padding="5" />
    </StackPanel>
    
  8. 右击LinkClick选择“导航到事件处理程序”,使用Frame对象的Navigate方法来加载一个页面,添加代码如下:
    private void LinkClick(object sender, RoutedEventArgs e) {
        HyperlinkButton button = (HyperlinkButton)sender;
        string viewSource = button.Tag.ToString();
        ContentFrame.Navigate(new Uri(viewSource, UriKind.Relative)); 
    }
  9. 运行,效果如下:
    image
  10. 注意,你可以点击浏览器的导航按钮来向前和向后导航。

导航框架的优点

Silverlight4对比前一版本有了大幅改进,增加了一堆新特性,例如浏览器历史支持和深度链接(deep linking)。

深度链接(Deep Linking)

Silverlight4的另一个优点是支持深度链接。深度链接是链接到应用程序的一个特殊状态页面的能力。

为了解析深度链接,假设有个应用程序已经加载和显示了主页。当用户点击主页上的链接时,应用程序导航到产品列表页面。这时用户可以点击导航到一个产品的详细页面。这个应用程序可以用以下图表示:

image

如果你想有个链接直接导航到产品B的详细页面?使用导航框架,Silverlight允许开发者在应用程序里链接到不同的状态。

NavigationService对象

前面那一节里,使用了Frame对象的Navigate方法改变页面。这需要一次又一次地访问寄宿在页面内的Frame对象。例如,考虑下图,你可以从主页轻松导航到View1.但是你想在View1的后置代码里转到Inner View1的话,你需要访问寄宿在View1的Frame对象来导航到Inner View1。

image

好在,Silverlight的导航框架包含一个可以访问寄宿这View的Frame对象的对象。这个对象就是NavigationService。下面通过练习学习使用NavigationService对象。

练习:使用NavigationService对象

这个练习是在前面练习基础上的,需要在Page1里添加一个按钮和使用NavigationService对象导航到InnerView1的点击事件。

  1. 打开刚才项目的Page1.xaml,添加一个按钮。修改为代码如下:
    <StackPanel>
        <TextBlock Text="View 1" FontSize="60" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" />
        <Button Click="Button_Click" Padding="10" Content="Navigate to Inner View" HorizontalAlignment="Center" />
    </StackPanel>
  2. 添加名为InnerPage的Silverlight页面,代码如下,和前面一样只是显示一个简单的文本。
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Background="Black">
        <TextBlock Text="Inner View 1" FontSize="40" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </StackPanel>
  3. 在Page1.xaml后置代码里添加按钮的处理程序,来实现导航到InnerPage。
    private void Button_Click(object sender, RoutedEventArgs e) {
        NavigationService.Navigate(new Uri("/InnerPage1.xaml", UriKind.Relative));
    }
  4. F5运行可得到如下效果,点击Navigate to Inner View可跳转到InnerPage
    image

这一节,学习了怎样使用NavigationService实现Silverlight页面的导航,下一节,将会学习使用NetworkContext对象在页面之间传递数据。

传递数据到导航页

在HTML页面,可以通过QueryString来传递数据到另一个页面。而在Silverlight应用程序是通过NavigationContext对象来传递数据的。例如,下面代码可以获得一个ProductID:

string productId = NavigationContext.QueryString["ProductID"].ToString(); 

练习:传递数据

在这个练习继续使用上节的项目,这里将会传递一些数据到InnerPage1.xaml里。

  1. 打开上一节的项目,打开Page1.xaml,修改代码来添加一个ComboBox,代码:
    <StackPanel>
        <TextBlock Text="View 1" FontSize="60" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" />
        <Button Click="Button_Click" Padding="10" Content="Navigate to Inner View" HorizontalAlignment="Center" />
        <ComboBox Padding="10" Margin="10" x:Name="Color" Width="100">
            <ComboBoxItem Content="Blue" IsSelected="True" />
            <ComboBoxItem Content="Red" />
            <ComboBoxItem Content="Green" />
        </ComboBox>
    </StackPanel>
  2. 接着打开page1.xaml的后置代码文件,编辑Button_Click事件处理程序,使用QueryString来传递选择的颜色:
    private void Button_Click(object sender, RoutedEventArgs e) {
        string color = Color.SelectionBoxItem.ToString();
        var uri = string.Format("/InnerPage1.xaml?Color={0}", color);
        NavigationService.Navigate(new Uri(uri, UriKind.Relative));
    }
  3. 打开InnerPage1.xaml,再在下面添加一个TextBlock来显示传递过来的数据:
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
        <StackPanel Background="Black">
            <TextBlock Text="Inner View 1" x:Name="ViewHeader" FontSize="40" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </StackPanel>
        <TextBlock Text="(Blue)" x:Name="ViewColor" FontSize="30" Foreground="Blue" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </StackPanel>
  4. 打开InnerPage1.xaml文件的后置代码,使用NavigationContext对象检索传递过来的数据,使用switch来处理颜色,代码如下:
    protected override void OnNavigatedTo(NavigationEventArgs e) {
        var color = NavigationContext.QueryString["Color"];
        Brush b;
    
        switch (color) {
            case "Red":
                b = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));
                ViewHeader.Foreground = b;
                ViewColor.Foreground = b;
                ViewColor.Text = "(Red)";
                break;
    
            case "Green":
                b = new SolidColorBrush(Color.FromArgb(255, 0, 255, 0));
                ViewHeader.Foreground = b;
                ViewColor.Foreground = b;
                ViewColor.Text = "(Green)";
                break;
    
            default:
                b = new SolidColorBrush(Color.FromArgb(255, 0, 0, 255));
                ViewHeader.Foreground = b;
                ViewColor.Foreground = b;
                ViewColor.Text = "(Blue)";
                break;
        }
    }
  5. F5运行,运行效果如下(InnerPage1页面浏览器的链接为:http://localhost:5379/NavAppFromScratchTestPage.aspx#/InnerPage1.xaml?Color=Red):
    image

这一节学习了通过QueryString的方式使用NavigationContext对象来传递数据。下一节探讨Uri的映射和怎么创建友好的uri来导航页面。

Uri映射

上面的练习里,你可能注意到在Frame里导航到不同页面时,浏览器的URL会改变。可能也会注意到这些URL并不怎么好看,还包含了一些你可能不想显示的信息,例如下面的链接:
 
http://www.domain.com/Catalog.aspx#ProductDetails.xaml?ID=4

如果链接改为下面这样会好很多:
http://www.domain.com/Catalog.aspx#Product/4

这个URL易读很多,更加友好。而且,它不会透露你应用程序的细节,可以通过使用Uri映射的特性来获得这个链接。

练习:使用Uri映射

这个练习里,将上面的项目改为使用Uri映射的方式来导航。

  1. 打开上面的项目。这里有三个页面需要使用Uri映射,Page1.xaml,Page2.xaml,InnerPage1.xaml。
  2. 打开App.xaml为导航框架添加xml命名空间:
    <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                 xmlns:nav="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation" 
                 x:Class="NavAppFromScratch.App"
                 >
  3. 添加UriMapper到Application Resources里,在UriMapper里,现在需要添加三个UriMapping元素,如下:
    <Application.Resources>
        <nav:UriMapper x:Key="uriMapper">
            <nav:UriMapping Uri="Page1" MappedUri="/Page1.xaml"/>
            <nav:UriMapping Uri="Page2" MappedUri="/Page2.xaml"/>
            <nav:UriMapping Uri="InnerPage/{c}" MappedUri="/InnerPage1.xaml?Color={c}" />
        </nav:UriMapper>
    </Application.Resources>
  4. 现在主页面上的两个超链接导航按钮可以改为如下:
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
        <HyperlinkButton Content="View 1" Click="LinkClick" Tag="Page1" Padding="5" />
        <HyperlinkButton Content="View 2" Click="LinkClick" Tag="Page2" Padding="5" />
    </StackPanel>
  5. 同样的,在后端也要修改,打开Page1.xaml.cs,修改按钮处理事件如下:
    private void Button_Click(object sender, RoutedEventArgs e) {
        string color = Color.SelectionBoxItem.ToString();
        var uri = string.Format("InnerPage/{0}", color);
        NavigationService.Navigate(new Uri(uri, UriKind.Relative));
    }
  6. 最后在MainPage.xaml里把UriMapper属性添加到Frame里:
    <nav:Frame x:Name="ContentFrame" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
        Margin="10" Grid.Row="1" BorderThickness="2" BorderBrush="Black" 
    UriMapper="{StaticResource uriMapper}"/>
  7. 运行效果:
    http://localhost:5379/NavAppFromScratchTestPage.aspx#InnerPage/Red

Uri路由

除了Uri映射外,Silverlight的导航框架还支持Uri路由。例如,如果你把所有页面放在名为“Views”的文件夹里,你可以按照这个命名约定设置理由映射:

<nav:UriMapping Uri="{}{p}" MappedUri="/Views/{p}.xaml" />

这个映射可以匹配所有在“Views”里的xaml文件。例如,View1可以匹配/Views/Views1.xaml。

posted @ 2012-05-12 14:22  zhangweiwen  阅读(799)  评论(2编辑  收藏  举报