天下网吧 >> 网吧方案 >> 网络方案 >> 正文

了解WPF中的路由事件和命令

690)、Presentation Model,在 WPF 循环中亦称做 Model View ViewModel (msdn.microsoft.com/library/cc707885),通常会出现这种情况。

    此时的问题是启用并处理命令逻辑可能不是直接归属于可视树,而是位于表示器或表示模型。此外,确定是否启用命令的状态与命令调用程序和视图在可视树中的位置无关。有时,您会遇到一个特殊命令在给定时间有多个处理程序的情形。

    要了解在哪些情况下路由命令会出现问题,请查看图 5。它是一个简单的窗口,包含一对用户控件,这两个控件以 MVP 或 MVC 模式表示视图。主窗口包含一个 File 菜单和工具栏,其中有 Save 命令按钮。在主窗口上方还有一个输入文本框,以及一个将 Command 设为 Save 的 Button。


图5复合用户界面(单击图像可查看大图)

    提示:挂接匿名方法

    在图 6 所示的代码中,我使用了我同事 Juval Lowy 传授给我的技巧,向声明中的委托挂接一个空的匿名方法。

    Action<string> m_ExecuteTargets = delegate { };这样,在调用委托前,您就不必再检查是否有空值,因为在调用列表中始终都有一个 no-op 订户。您还可能通过在多线程环境中取消订阅避免可能的争用,如果您检查空值,经常会出现争用。

    有关此技巧的详细信息,请参阅 Juval Lowy 撰写的《Programming .NET Components, Second Edition》。

    UI 的其余部分由两个视图提供,每个都是简单用户控件的实例。每个用户控件实例的边界颜色各不相同,这是为更清楚地显示它们所提供的 UI 内容。每个用户控件实例都有一个 Save 按钮,它将 Command 属性设为 Save 命令。

    路由命令(与可视树中的位置密切相关)带来的困难在这一简单示例中一览无余。在图 5 中,窗口本身没有针对 Save 命令的 CommandBinding。但它的确包含该命令的两个调用程序(菜单和工具栏)。在此情形中,我不想让顶层窗口在调用命令时必须了解采取何种操作。而 是希望由用户控件表示的子视图处理命令。此例中的用户控件类有针对 Save 命令的 CommandBinding,它为 CanExecute 返回 true。

    但在图 5 中,您可以看到焦点项位于顶部文本框的窗口内,而此级别的命令调用程序却被禁用。此外,尽管用户控件中没有焦点项,但用户控件中的 Save 按钮却被启用。

    如果您将焦点项从一个文本框更改到一个用户控件实例内,菜单和工具栏中的命令调用程序会变为启用状态。但窗口本身的 Save 按钮不会变为启用状态。实际上,在这种情况下无法用正常路由启用窗口上方文本框旁的 Save 按钮。

    原 因仍与单个控件的位置相关。由于在窗口级没有命令处理程序,尽管焦点项位于用户控件之外,但可视树上方或焦点项路径上仍没有命令处理程序会启用挂接为命令 调用程序的控件。因此一旦涉及这些控件,会默认禁用命令。但是,对于用户控件内的命令调用程序,由于处理程序在可视树的位置靠上,所以会启用命令。

    一旦您将焦点项转到其中一个用户控件内,位于窗口和焦点项路径上文本框之间的用户控件即会提供命令处理程序,用于为工具栏和菜单启用命令,这是因为它们会检查焦点项路径以及其在可视树中的位置与根项之间的路径。由于窗口级按钮和根项之间没有处理程序,所以无法启用该按钮。

    要是这个简单的小示例中的可视树和焦点项路径的繁文缛节就让您倍感头疼,如果 UI 相当复杂,在可视树中众多不同位置有命令调用程序和处理程序,要想理顺命令启用和调用有多难就可想而知了。那会您联想起电影《Scanners》中的怕人情节,让人头昏眼花。

    避免命令出错

    要 防止路由命令出现与可视树位置相关的问题,您需要保持简洁。通

本文来源:天下网吧 作者:网吧方案

相关文章
没有相关文章
声明
声明:本站所发表的文章、评论及图片仅代表作者本人观点,与本站立场无关。若文章侵犯了您的相关权益,请及时与我们联系,我们会及时处理,感谢您对本站的支持!联系Email:support@txwb.com,系统开号,技术支持,服务联系QQ:1175525021本站所有有注明来源为天下网吧或天下网吧论坛的原创作品,各位转载时请注明来源链接!
天下网吧·网吧天下