1. Journal 的使用
Journal 用于在 XAML 浏览器应用程序(XBAP)中维护历史访问页。删除前一访问页只需调当前 NavigationService 对象的 RemoveBackEntry() 即可;而增加一个访问页则复杂得多:
1) 实现一个 CustomContentState 的派生类,每个对象对应一个要保存的访问页,其中数据结构用于维护这个历史访问页的数据,在构造的时候通过适当的参数传入。它必须标上 Serializable() 属性。在这个类里要重载一个 Replay 方法和一个 JournalEntryName。Replay 一般通过向构造时传入的页面回调提供数据,恢复出历史页面。JournalEntryName 就是这个项目显示在访问历史下拉列表中的名称。
2) 相关页面需要实现 IProvideCustomContentState 接口。这个接口必须实现 GetContentState 函数,这个函数用于在当前页面上发生浏览切换时对浏览服务 NavigationService 提供一个 CustomContentState。
3) 在需要保存的状况下(如用户对页面进行变动时)对页面调用 NavigationService.AddBackEntry 手动进行快照。
2. NavigationService 的事件
页面浏览事件不是接力事件(Routed Events),且在一切的浏览过程中(如通过 NavigationService 调用或超链接访问)均会发生。以下依次罗列一次页面浏览发生的事件:
Navigating | 开始转向指定的页面 |
Navigated | 浏览启动后但最终页面送达之前发送的一个事件 |
NavigationProgress | 在页面加载过程中每传送1KB数据发生的一个事件 |
LoadCompleted | 页面送达后发送的第一个事件 |
FragmentNavigation | 如果访问指向目标页面的某个单元,则在转向该单元时发送这个事件 |
此外 NavigationStopped 和 NavigationFailed 分别表示 StopLoading 导致浏览取消(不包括在 Navigating 事件响应中 Cancel)和浏览目标页面失败的事件。
3. WPF的后台任务
msdn 上有个例子值得一看,它同时详细说明了 BackgroundWorker 和 Monitor 的使用:
http://msdn.microsoft.com/library/system.threading.monitor.pulse(VS.95).aspx
注意其中多个 m_worker 通过 ProgressChanged 回调对 outputBlock.Text 可以做到直接且互斥的访问,说明 WPF 的后台任务是一种不同于一般线程的特殊的机制(小范蛙注:很有可能是通过 Windows API 中的 SendMessage 或类似的机制,这种机制在 .NET Framework 中也有应用,即控件的 Invoke 方法,它通过在控件所在的窗口线程上 [而非调用它的线程上] 执行方法来避免非串行的调用)。如果不使用这个方法,就需要在线程中调 m_worker.ReportProgress 的地方改用调 outputBlock.Dispatcher.BeginInvoke 的方法更新 outputBlock 内容。
4. 工程中的Settings
在工程属性中的 Settings 可以作为 Properties.Settings.Default 的同名属性(由开发环境即时生成)直接访问,并且类型一致。调用 Properties.Settings.Default.Save 方法即可保存。这和基于 XML 保存的 Application Settings 不同。(小范蛙补充:这个是自动生成的类,是强类型的,有助于避免程序引用不存在的设置项。)
5. 命令
命令相对事件来说比较独立。命令的组成:
1) 命令定义:定义一个命令。类型为 RoutedUICommand,通常作为静态属性封装在一个类中。
2) 命令绑定:连接命令和(多个)处理函数的桥梁。有代码绑定(UIElement 的 CommandBindings 集合)和 XAML 直接绑定两种方法。通过各层单元的命令绑定,实现命令上浮式(Bubbling)搜索。(注意,命令不同于事件接力,其传递过程中一旦遇到处理方法,就不再继续传递,参考资料 2 似乎也报告了这个问题)
3) 命令激发:触发命令的条件。主要有控件直接触发(实现 ICommandSource 控件的 Command 属性)、手势触发(命令的 InputGestures 集合,可在构造时添加)和代码触发(命令的 Execute 方法)三种方法。
6. 事件
接力事件(或路由事件,Routed Events)完全奉行下沉式(Tunneling)和上浮式(Bubbling)接力过程。事件处理方法可以通过 XAML 直接静态绑定,或用 AddHandler(或 += 操作)动态绑定(小范蛙注:此处 AddHandler 不是指 VB.NET 的关键词 AddHandler)。
参考资料
1. http://msdn.microsoft.com/magazine/cc785480.aspx#id0190070
2. http://social.msdn.microsoft.com/forums/wpf/thread/1fb817dc-4f6f-4d2c-8bdf-624b26a0ed45/
3. http://joshsmithonwpf.wordpress.com/2008/03/18/understanding-routed-commands/(这则会导引至 CodeProject 和 MSDN 的几篇比较深入的文章)