Windows Presentation Foundation把管线和服务集中在一个类型(System.Windows.application)中了,你可以在标记(XAML)、代码(C#或 Visual Basic)、或者两者组合(标记和后台代码)中使用它。Application类型变得如此重要,以至于Visual Studio 2005会自动地向每个新的.NET Framework 3.0(以前的WinFX)窗体应用程序项目添加该类型的一个实例:
// MainWindow.xaml.cs (codebehind) using System.Windows; public partial class MainWindow : Window { ... } 在添加窗体定义之后,Visual Studio 2005自动地把标记文件的"构建类型"设置为Page(页面)。在构建的时候,该标记被转换为一种特定的资源类型,可以被统一的资源标识符(URI)唯一地识别出来。从本质上说,这使得Windows Presentation Foundation可以使用URI宣告式地载入一个窗体,你可以使用这种能力来指定一个应用程序启动时自动打开的窗体。要达到这个目的,只需要设置标记中的Application.StartupUri属性,如下所示:
sealed class NavigationService : IContentContainer { // 导航 public bool Navigate(Uri source); // 导航到URI public void Refresh(); // 重新导航到当前内容 public void StopLoading(); // 停止当前的导航 // 导航历史 public bool CanGoBack { get; } // Content in back nav. history? public bool CanGoForward { get; } // Content in forward nav. history? public void GoBack(); // Go to previous content in nav. history public void GoForward(); // Go to next content in nav. history
// 导航的生命周期 // 导航请求 public event NavigatingCancelEventHandler Navigating; // 导航到内容 public event NavigatedEventHandler Navigated; // 内容载入了 public event LoadCompletedEventHandler LoadCompleted; // 导航错误 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)是我们应该努力的方向。
为了建立一个XBAP示例应用程序,需要在Visual Studio 2005中建立一个新的.NET框架组件3.0 Web浏览器应用程序,并复制示例NavigationWindow文件,就完成工作了。作为结果生成的应用程序将寄宿在Internet Explorer中运行,如图11所示。
Windows Presentation Foundation应用程序模型是非常灵活的。它支持标准的和浏览器寄宿的应用程序--它们两者都支持菜单驱动和超链接驱动的导航。此外,应用程序的内容可以被封装到应用程序的部件、被引用的部件或某些位置的松散文件中。总而言之,在Windows Presentation Foundation应用程序模型中建立的用户体验类型仅受个人选择的限制。