Silverlight 3 Beta 新特性解析(6) - Navigation和Deep Linking篇
前提条件:
阅读本文之前请确认你已经安装了如下软件
- Visual Studio 2008 (Express) SP1
- Silverlight 3 Tools For Visual Studio
- Microsoft Expression Blend 3 MIX 09 Preview
本篇主要内容:
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">
-
导航历史记录
现在我们有了新的导航机制,就可以在浏览器上记录下曾经浏览过的页面了,如下图所示
其主要是靠NavigationService中的GoBack以及GoForward来实现后退以及前进功能的
-
NavigationService和NavigationContext
有了Frame来控制导航还是不够的
比如下图是一个Page控件,我先点击查看联系信息按钮来查看雇员的联系信息
而由于页面空间有限,所以我想把雇员信息放置到另外一个页面中
而在这个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表
其通过ContactID将两个表关联起来
本文的项目结构如下
修改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);
}
}
Deep Linking:
从上面的范例,我们可以看到,我们已经不知是能查看初始的载入的雇员页面
我们也可以输入类似的网址如http://localhost:3066/Default.aspx#/ContactID=1006
来直接查看联系编号为1006的雇员的联系方式,如下
这就是传说中的深度链接了(Deep Linking)
这样搜索引擎就可以搜索到下一级的页面了,改善了SEO效果
-
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>
代码下载:
出处:http://ibillguo.cnblogs.com/
本文版权由作者和博客园共同所有,转载请注明出