public event NavigationFailedEventHandler NavigationFailed; // 下载的字节数 public event NavigationProgressEventHandler NavigationProgress; // 导航停止了 public event NavigationStoppedEventHandler NavigationStopped;
// 内容 public object Content { get; set; } // 当前载入的内容 public Uri CurrentSource { get; } // 当前内容的URI public Uri Source { get; set; } // 当前内容的URI,或者将导航到的内容的URI
// 查找导航服务 public static NavigationService GetNavigationService(DependencyObject dependencyObject); } 当你知道这些内容之后,就能使用GetNavigationService来获取寄宿页面的NavigationWindow的NavigationService引用了:
// HomePage.xaml.cs (codebehind) public partial class HomePage : Page { void viewHyperlink_Click(object sender, RoutedEventArgs e) { // 查看订单 ViewOrderPage page = new ViewOrderPage(GetSelectedOrder()); NavigationService ns = NavigationService.GetNavigationService(this); ns.Navigate(page); } Order GetSelectedOrder() { ... } ... } 这就使得页面可以执行导航而无需知道宿主的特定信息了。这种需求是如此的普遍,以至于页面提供了一个特定的辅助属性NavigationService,它提供的功能相同:
// HomePage.xaml.cs (code-behind) public partial class HomePage : Page { void viewHyperlink_Click(object sender, RoutedEventArgs e) { // 查看订单 ViewOrderPage page = new ViewOrderPage(GetSelectedOrder()); this.NavigationService.Navigate(page); }
Order GetSelectedOrder () { ... } ... } 图9演示了NavigationWindow、NavigationService和页面(Page)之间的关系。你可以看到,NavigationWindow重新实现了自己的NavigationService的Content属性。NavigationWindow不但用这种方法实现了NavigationService的大多数成员,甚至于还增加了一些。例如,你可以通过BackStack和ForwardStack属性,枚举"向前"和"向后"导航历史的内容。
图9:关系
不幸的是,你无法建立自定义的、聚合了NavigationService的类型(尽管它是一个公共类型,但是它有内部的构造函数,从而阻止了实例化)。作为代替,你必须依赖三种NavigationService聚合器(aggregator)来寄宿内容。这就是我们所知道的导航器(navigator),包括NavigationWindow、Frame和浏览器(仅包括用于Windows Presentation Foundation 1.0的Internet Explorer 6 和 7)。当编写代码让页面使用自己的NavigationService属性的时候,它就可以寄宿在上面的三种导航器中,而不需要做任何更改,如图10所示。
NavigationWindow、页面和超链接为用户在独立的应用程序中获得浏览器样式的用户体验提供了一条很好的途径。总而言之,NavigationWindow是一个浏览器,虽然它没有目前的浏览器所带有的所有功能(例如收藏夹、分页浏览等等)。由于大多数用户都有浏览器的知识,他们对提供同等能力、甚至集成浏览器的应用程序的感觉会更好。如果你的应用程序从浏览器寄宿和超链接驱动的环境中受益,那么Windows Presentation Foundation XAML浏览器应用程序(XBAP)是我们应该努力的方向。