博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Silverlight控件之Frame、Page[转载]

Posted on 2010-04-24 13:15  小高好孩子  阅读(3623)  评论(1编辑  收藏  举报

本篇主要内容:

  Navigation

  Frame和Page控件

  导航历史记录

  NavigationService和NavigationContext

  DeepLinking

  UriMapper和UriMapping

  导航(Navigation):

  在Silverlight 2时代,如何从一个控件页面导航到另外一个控件页面是需要费很大功夫的事情

  以至于国外有不少人研究并制作了自己的导航控件,如Peter Brown 和 Gerard Leblanc

  但是可用性还是比较差,于是大家在进行Silverlight 2开发的时候碰到导航问题经常就卡壳了

  Silverlight 3终于将导航框架引进了Silverlight

  其主要依赖的两个控件是Frame和Page控件(和WPF一样)

  Frame和Page控件

  Frame控件用来放置Page控件并执行导航功能,其主要的属性和方法如下:

  Source

  用于设置第一次加载Frame时加载那个Page控件

  如下就是加载Views目录下的EmployeePage.xaml页面控件

<navigation:Frame x:Name="NavFrame" Source="/Views/EmployeePage.xaml"/>

Navigate(Uri uri)

  这个方法用于在不同页面间进行导航,其中Uri就类似于ASP.Net中的页面路径

  只是这里的页面是.xaml而不是.aspx

  如下表示名字为NavFrame的这个Frame控件现在将导航至Views目录下的ContactPage.xaml页面

this.NavFrame.Navigate(new Uri("/Views/ContactPage.xaml", UriKind.Relative));

  而作为Frame控件的亲密战友,其和普通的用户控件事实上别无二致

  除了其能被Frame调用,而且其有个Title属性用来设置这个页面标题并显示在浏览器上,如下

<navigation:Page x:Class="SL3Beta.Nav.Views.EmployeePage" 

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 

      xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

      Title="Employee Page">

Silverlight 3 Beta 新特性解析(6) - Navigation和Deep Linking篇

  导航历史记录

  现在我们有了新的导航机制,就可以在浏览器上记录下曾经浏览过的页面了,如下图所示

Silverlight 3 Beta 新特性解析(6) - Navigation和Deep Linking篇

其主要是靠NavigationService中的GoBack以及GoForward来实现后退以及前进功能的

  NavigationService和NavigationContext

  有了Frame来控制导航还是不够的

  比如下图是一个Page控件,我先点击查看联系信息按钮来查看雇员的联系信息

Silverlight 3 Beta 新特性解析(6) - Navigation和Deep Linking篇

  图片看不清楚?请点击这里查看原图(大图)。

  而由于页面空间有限,所以我想把雇员信息放置到另外一个页面中

  而在这个Page控件如何导航到下一个页面呢

  答案是使用NavigationService类来导航(只有在Page控件中才起作用),如下

private void ViewContactButton_Click(object sender, RoutedEventArgs e)

{

  Employee employee = this.EmployeeGrid.SelectedItem as Employee;

  if (employee != null)

  {

    this.NavigationService.Navigate(new Uri(String.Format("/Views/ContactPage.xaml?ContactID={0}", employee.ContactID), UriKind.Relative));

  }

}

  我们可以导航,而且还可以在页面间传参数

  大家是不是有点似曾相识的感觉啊,没错,这就是借鉴了ASP.Net采用QueryString来传递参数的机制

  现在留下来的问题就是如何在另外一个页面中获取得到传递过来的参数了

 这个工作是由NavigationContext来完成的,如下

if (this.NavigationContext.QueryString.ContainsKey("ContactID"))

{

  int contactID = Int32.Parse(this.NavigationContext.QueryString["ContactID"]);

}

  下面我用一个实际的例子把这些知识串起来

  由于本篇将采用ADO.Net Entity Framework还有.Net RIA Services技术来获取并处理数据

  所以如果不了解的,请先查看下Silverlight 3 Beta 新特性解析(5) - Data篇

  也就是前面的如何创建项目以及采用ADO.Net Entity Data Model来获取数据

  并采用Domain Service类来提供网络服务的将一概略过

  本篇依然采用AdventureWorks数据库来示范

  本文将采用的是Employee和Contact表

Silverlight 3 Beta 新特性解析(6) - Navigation和Deep Linking篇

  其通过ContactID将两个表关联起来

  本文的项目结构如下

Silverlight 3 Beta 新特性解析(6) - Navigation和Deep Linking篇

  修改PersonDomainService.cs类如下

public IQueryable<Contact> GetContactByContactID(int contactID)

{

  return this.Context.Contact.Where(e=>e.ContactID==contactID);

}

  也就是我们将通过输入contactID来获取雇员的联系信息

而在SL3Beta.Nav项目下创建的Views目录用来存放页面控件

  MainPage.xaml是普通的用户控件,其代码如下

<UserControl x:Class="SL3Beta.Nav.MainPage"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation">

  <Grid x:Name="LayoutRoot" Background="#606060">

    <navigation:Frame x:Name="NavFrame" Source="/Views/EmployeePage.xaml">

    </navigation:Frame>

  </Grid>

</UserControl>

  在初始的状态下加载/Views/EmployeePage.xaml页面来显示雇员信息如下:

<navigation:Page x:Class="SL3Beta.Nav.Views.EmployeePage" 

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 

      xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

      xmlns:web="clr-namespace:SL3Beta.Nav.Web"

      xmlns:riaData="clr-namespace:System.Windows.Data;assembly=System.Windows.Ria.Controls"

      xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"

      xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

      xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"

      Title="Employee Page">

  <Grid x:Name="LayoutRoot">

    <StackPanel Width="900" Margin="10">

      <riaControls:DomainDataSource x:Name="EmployeeDataSource" LoadSize="10" LoadMethodName="LoadEmployee">

        <riaControls:DomainDataSource.DomainContext>

          <web:PersonDomainContext/>

        </riaControls:DomainDataSource.DomainContext>

        <riaControls:DomainDataSource.SortDescriptors>

          <riaData:SortDescriptor Direction="Ascending" PropertyPath="EmployeeID"/>

        </riaControls:DomainDataSource.SortDescriptors>

      </riaControls:DomainDataSource>

 

      <data:DataGrid x:Name="EmployeeGrid" ItemsSource="{Binding Data,ElementName=EmployeeDataSource}" MinHeight="100" SelectionChanged="EmployeeGrid_SelectionChanged"></data:DataGrid>

 

      <dataControls:DataPager PageSize="10" Source="{Binding Data,ElementName=EmployeeDataSource}"></dataControls:DataPager>



      <Button Content="查看联系信息" x:Name="ViewContactButton" HorizontalAlignment="Right" Margin="20,5" Click="ViewContactButton_Click" IsEnabled="False"/>

    </StackPanel>

  </Grid>

</navigation:Page>

其中查看联系信息按钮用来触发导航到选中的雇员的联系信息,其代码如下

private void ViewContactButton_Click(object sender, RoutedEventArgs e)

{

  Employee employee = this.EmployeeGrid.SelectedItem as Employee;

  if (employee != null)

  {

    this.NavigationService.Navigate(new Uri(String.Format("/Views/ContatctPage.xaml?ContactID={0}", employee.ContactID), UriKind.Relative));

  }

}

  而ContactPage.xaml文件

<navigation:Page xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm" x:Class="SL3Beta.Nav.Views.ContactPage" 

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 

      xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

      Title="Contact Page" Width="400" Height="400">

  <Grid x:Name="LayoutRoot">

    <dataControls:DataForm x:Name="ContactForm"></dataControls:DataForm>

  </Grid>

</navigation:Page>

 将接收由HomePage.xaml传过来的参数如下,并通过服务来获取得到详细的联系信息并用DataForm显示出来

protected override void OnNavigatedTo(NavigationEventArgs e)

{

  if (this.NavigationContext.QueryString.ContainsKey("ContactID"))

  {

    int contactID = Int32.Parse(this.NavigationContext.QueryString["ContactID"]);

 

    _personContext.Loaded += (sender, e2) =>

      {

        if (_personContext.Contacts.Count>0)

          this.ContactForm.CurrentItem = _personContext.Contacts[0];

      };

    _personContext.LoadContactByContactID(contactID);

  }

}

Silverlight 3 Beta 新特性解析(6) - Navigation和Deep Linking篇

  你也可以通过后退键来查看原来所有的雇员的详细信息

  Deep Linking:

  从上面的范例,我们可以看到,我们已经不知是能查看初始的载入的雇员页面

  我们也可以输入类似的网址如http://localhost:3066/Default.aspx#/ContactID=1006

  来直接查看联系编号为1006的雇员的联系方式,如下

Silverlight 3 Beta 新特性解析(6) - Navigation和Deep Linking篇

这就是传说中的深度链接了(Deep Linking)

  这样搜索引擎就可以搜索到下一级的页面了,改善了SEO效果

  但是这样可能会暴露网站的目录结构

  我们可以使用Uri映射来解决这个问题如下

  UriMapper和UriMapping

  其中上述两个控件都位于System.Windows.Navigation这个名字空间中

  所以我们在MainPage.xaml文件中引用其如下

  xmlns:windowsNav="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"

  并修改MainPage.xaml的Frame控件如下

<navigation:Frame x:Name="NavFrame" Source="Employee" HorizontalAlignment="Center" VerticalAlignment="Center">

  <navigation:Frame.Resources>

    <windowsNav:UriMapper x:Name="uriMapper">

      <windowsNav:UriMapping MappedUri="{}/Views/EmployeePage.xaml" Uri="Employee"/>

      <windowsNav:UriMapping MappedUri="{}/Views/ContactPage.xaml?ContactID={contactID}" Uri="ContactID={contactID}"/>

    </windowsNav:UriMapper>

  </navigation:Frame.Resources>

</navigation:Frame>

  这样我们就将/Views/EmployeePage.xaml映射成Employee

  而/Views/ContactPage.xaml?ContactID={contactID}被映射成ContactID={contactID}

  对映射前和映射后的网络路径比较如下

出处:http://ibillguo.cnblogs.com/

  系列文章:

Silverlight 3 Beta 新特性解析(1) - 概论

Silverlight 3 Beta 新特性解析(2)-Graphics篇

Silverlight 3 Beta 新特性解析(4) - 离线功能篇

Silverlight 3 Beta 新特性解析(3) - Media篇

 

Silverlight 3 Beta 新特性解析(5) - Data篇