logo资料库

WPF/Silverlight实现右键弹出菜单功能详解.pdf

第1页 / 共102页
第2页 / 共102页
第3页 / 共102页
第4页 / 共102页
第5页 / 共102页
第6页 / 共102页
第7页 / 共102页
第8页 / 共102页
资料共102页,剩余部分请下载后查看
GridView 有一个 Columns 内容属性,其中保存了一个 GridViewColumn 对象的集合,也保存了一些控 制列 header 的行为的其他属性。WPF 定义了一个派生自 ListBoxItem 的 ListViewItem 元素。在这种情况下, DateTime 对象隐式地包装在 ListViewItem 当中,因为它们没有被显式地使用。 与 ListBox 一样,ListView 的项是一个简单的列表,所以在每个列中显示不同数据的关键是 GridViewColumn 的 DisplayMember Binding 属性。ListView 为每一行保存了一个复杂的对象,而每一列的值 是该复杂对象的属性或者子属性。与 ItemsControl 的 DisplayMemberPath 属性不同,DisplayMember Binding 需要使用第 9 章介绍的数据绑定技术。 GridView 最棒的地方是它自动支持一些资源管理器中详细视图(Detail view)的高级特性: ·通过拖拉列对列重新排序。 ·拖动列的分隔器(separator)可以改变列尺寸。 ·通过双击列的分隔器后,GridView 会根据当前内容来自动调整列尺寸。 然而,点击列的头(header)并不会自动排序,这是个功能上的缺陷。当点击头时进行排序的代码并不 复杂(因为能使用前一节提到的 SortDescriptions 属性),但是也不得不在头里手工创建小箭头,这样可以 告诉用户哪一个列被排序了,是升序还是降序。 6.TabControl 最后介绍的选择器(selector)控件是 TabControl,用它可以在多个页面之间进行切换。图 4-17 显示了 一个基本 TabControl 的外观。TabControl 上的标签通常都位于控件的顶部,但是通过使用 TabControl 的 TabStripPlacement 属性(Dock 类型),可以把它的位置设为左边、右边或者下边。 TabControl 的使用非常简单。往里面添加项就可以了,每一个项会被放置在一个单独的标签里。例如: 23 更多电子书教程下载请登陆http://down.zzbaike.com/ebook 本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
这很像使用 ComboBoxItem 的 ComboBox、使用 ListBoxItem 的 ListBox。TabControl隐式地用它的 TabItem 类型包装每一个项。然而,你不太可能直接把非 TabItem 添加到 TabControl 中,由于没有一个显式的 TabItem, 就没有办法产生相应的标签。例如,以下 XAML 代码是图 4-17 的源代码: 图 4-17 WPF TabControl TabItem 是带有头的内容控件,所以它的头可以是任何类型的对象,就像 GroupBox 或者 Expander 一样。 与其他选择器不同,TabControl 的第 1 个项默认是被选中的。你也可以用编程的方式把 SelectedItem 设 为 null(或者把 SelectedIndex 设置为1),这样就可以取消选择所有的标签页。 4.2.2 菜单 WPF 内建了两种菜单——Menu 和 ContextMenu(上下文菜单)。和 Win32 技术不同,WPF 的菜单不 是覆盖在其他控件上面,并没有这样或那样的限制,它们是另一种 Items 控件,它是为项能够在一系列弹出 情况下层次化显示而设计的。 1.Menu Menu 是水平放置它的项的,默认情况下把灰色栏作为背景。把 Menu 添加到它的 ItemsControl 基类的 唯一公开的 API 是 IsMainMenu 属性。当为 true(默认的)时,用户按下 Alt 或者 F10 键,菜单获得焦点, 这点符合 Win32 菜单用户的习惯。 与其他 Items 控件一样,Menu 的项可以是任何东西,但是你应该使用 MenuItem 以及 Separator 对象。 图 4-18 显示了代码清单 4-3 的 XAML 创建的常规菜单。 代码清单 4-3 含有 MenuItem 以及 Separator 子菜单的常规菜单 24 更多电子书教程下载请登陆http://down.zzbaike.com/ebook 本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
图 4-18 WPF 菜单 MenuItem 是带头的 Items 控件(继承自 HeaderedItemControl),这个和带头的内容控件非常像。对于 MenuItem,它的头实际上是主对象(通常是文字,如图 4-18 所示)。如果 Items 是子元素的话就会被作为 子菜单显示。和按钮、标签控件一样,MenuItem 使用下划线前缀来支持访问键(access key)。 Separator(分隔线)是一种简单控件,当被放在 MenuItem 里时,它会被如图 4-18 那样以水平线渲染。 Separator 也是为其他两个 Items 控件设计的,本章后面会讨论到 ToolBar 和 StatusBar。 尽管 Menu 是一个简单的控件,但 MenuItem 包含了许多用来自定义自己行为的属性。其中一些很有趣: ·Icon——允许把任意类型的对象添加到 Header 旁边。Icon 对象会像 Header 一样被渲染,尽管它通常 是一幅小图片。 ·IsCheckable——让 MenuItem 的行为像一个 CheckBox 控件。 ·InputGestureText——用一个相关的手势(gesture)来标识一个项(最常见的就是键盘快捷方式,比如 Ctrl+O)。 MenuItem 也定义了 5 个事件:Checked、Unchecked、SubmenuOpened、SubmenuClosed 和 Click。尽管 处理 Click 事件是一种通用的添加 MenuItem 行为的方式,但是你也可以将一个命令赋给 MenuItem 的 Command 属性。 25 更多电子书教程下载请登陆http://down.zzbaike.com/ebook 本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
注意 设置 InputGestureText 不会为 MenuItem 提供键盘快捷方式! 与 Windows Forms 或者 Visual Bas ic 6 不同,把 MenuItem 的 InputGetsureText 属性设置为字符串“Ctrl+O” 不会自动在按下“Ctrl+O”后自动调用该菜单项!要为 MenuItem 设置一个键盘快捷键,你应该用它的 Command 属性。如果那个命令已经被关联到输入手势(input gesture)上,MenuItem 的 InputGestureText 属 性会自动被设置为正确的字符串,这样不用任何额外的动作就可以显示这个快捷方式。 提示 当把 MenuItem 的 Command 属性赋给一个 RoutedUICommand 的实例时,它的 Header 会自动被设 置为 command 的 Text 属性!也可以显式地设定 Header 来重载该行为。 怎样让 Menu 垂直而不是水平排列菜单项? 因为 Menu 就是一种 Items 控件,所以可以用之前在 ListBox 一节中提到的相同 ItemsPanel 技巧,但是 需要把默认的面板替换为 StackPanel: StackPanel 的默认方向是垂直的,所以不需要去设置 Orientation 属性。运行结果如图 4-19 所示。 如果你想整个菜单都旋转到垂直方向上(就像在 Microsoft Office 里拖住菜单,然后把它停靠在窗口的 左侧边缘或者右侧边缘一样),应该使用下一章讨论的 RotateTransform。 图 4-19 垂直菜单 2.ContextMenu ContextMenu 和 Menu 工作原理一样。它是一种保存 MenuItem 和 Separator 的简单容器。但不能直接把 ContextMenu 嵌入到一个元素树中,必须通过一个适当的属性把它加载到控件上,比如使用由 FrameworkElement 和 FrameworkContentElement 定义的 ContextMenu 属性。当用户在控件上右击(或者按下 Shift+F10)时,上下文菜单就被显示出来。 图 4-20 显示了一个应用到 ListBox 上的上下文菜单,它使用了与代码清单 4-3 完全一样的 MenuItem: 26 更多电子书教程下载请登陆http://down.zzbaike.com/ebook 本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
图 4-20 WPF ContextM enu 除了 IsOpen 属性以及 Opened/Closed 事件,ContextMenu 定义了许多用来定制菜单位置的属性。默认情 况下,菜单左上角位于鼠标指针处,但是可以把它的 Placement 改成一个非 MousePoint 的值(如 Absolute), 或者设置它的 HorizontalOffset 以及 VerticalOffset 属性,来调整这个行为。 就像 ToolTip 有一个 ToolTipService 静态类,用来控制 ToolTip 目标的属性,ContextMenu 也有一个同 样目的的 ContextMenuService 静态类,它包含了许多附加属性,分别对应那些由 ContextMenu 直接定义的 属性。 当右键点击一个被禁用的元素时,怎样让 context 菜单显示? 与 ToolTipService 类似,ContextMenuService 包含了一个 ShowOnDisabled 附加属性,用来做这件事情。 你可以像这样使用它: 4.2.3 其他 Items 控件 剩下的 Items 控件有 TreeView、ToolBar 和 StatusBar,它们既不是选择器也不是菜单,但仍然可以包含 很多任意类型的对象。 1.TreeView TreeView 是一种常用控件,它会用可展开和折叠的节点来分层显示数据,如图 4-21 所示。在 Aero 主 题下,节点用三角来表示展开/折叠状态,但是在其他主题中(比如 Luna)则用+和-来表示。 27 更多电子书教程下载请登陆http://down.zzbaike.com/ebook 本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
图 4-21 WPF 的 TreeView TreeView 和 Menu 一样,也是一种简单控件。它可以包含任何项,并把这些项垂直排列。但是如果不 用 TreeViewItem 来填充它的话,TreeView 就没意义。TreeViewItem 就像 MenuItem 一样,是一种带有头的 控件,它的 Header 属性包含着当前的项,而它的 Items 集合中保存着子项(子项也是 TreeViewItem)。 图 4-21 中的 TreeView 能用以下 XAML 来创建: TreeViewItem 有两个方便的属性 IsExpanded 和 IsSelected,还有 4 个事件,分别对应于这两个属性的 4 种状态:Expanded、Collapsed、Selected 和 Unselected。TreeViewItem 同样支持富键盘导航,加号和减号键 可以展开或折叠一个项,箭头方向键、Page Up、Page Down、Home 和 End 键可以从一个项向另一个项移动 焦点。 注意 在 TreeView 中一定要显式地用 TreeViewItem 包装 Item! 你可能会临时使用 TextBlock 作为叶节点,但这样可能会陷入微妙的属性值继承陷阱,那会使 TextBlock 中的字体消失。例如,使一个父节点高亮会把它的前景色改为白色,并且如果 TextBlock 是直接的逻辑子 28 更多电子书教程下载请登陆http://down.zzbaike.com/ebook 本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
节点,它们的文字也会被变为白色。(尽管隐式的 TreeViewItem 是每一个 TextBlock 的可视父节点,但逻 辑父节点优先。)在默认的白色背景的映衬下,文字就不能被显示。如果把 TreeViewItem 变为每一个 TextBlock 的显式(逻辑)父节点,这种不合理的继承就不会再发生。 TreeView 与 Selector TreeView 的 API 使它看起来像一个 Selector,但是它不是从 Selector 继承而来的,因为它的层次项不能 自然地用简单整数来索引。因此,TreeView 类定义了自己的 SelectedItem 以及 SelectedValue 属性(但是没 有定义 SelectedIndex)。它还定义了 SelectedItem- Changed 事件,可以把 OldValue 和 NewValue 项传给其 他的事件处理程序,这是因为 TreeView 仅处理一个选择。 2.ToolBar ToolBar 控件会对许多小的按钮(或者其他控件)进行分组,它是对传统菜单系统的一种增强。图 4-22 显示了一个用以下 XAML 创建的 ToolBar: 图 4-22 WPF ToolBar 注意,用在 ToolBar 中的 Button 和 ComboBox 看起来和它们平时不一样。另外,Separator 也被渲染为 垂直线而不是水平线。由于 ToolBar 重载了项的默认样式,所以当它们被放在一个 ToolBar 中时会自动变成 大部分人所期望看到的样子。 ToolBar 可以被放在元素树的任何地方,但是通常把它们放在一个叫作 ToolBarTray 的 FrameworkElement 中。ToolBarTray 拥有一个 ToolBar 集合(在叫作 ToolBars 的内容属性里)。除非 ToolBarTray 29 更多电子书教程下载请登陆http://down.zzbaike.com/ebook 本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
的 IsLocked 属性被设置为 true,不然用户就可以拖曳 ToolBar 或重新定义 ToolBar。(ToolBarTray 同样定 义了一个 IsLocked 的附加属性,它可以被放在单独的 ToolBar 上。)ToolBarTray 有一个 Orientation 属性, 可以把它设置为 Vertical 使其所有的 ToolBar 垂直排列项。 如果 ToolBar 包含项的数量大于它的显示范围,多余的项就会转移到一个溢出区域。通过点击控件最后的小 箭头,溢出区域就会弹出来,如图 4-23 所示。默认都是最后一个元素第一个被移到溢出区域,但是你能通 过 OverflowMode 附加属性来控制每个项的溢出行为。有了这个属性,你就可以把一个项标记为 AsNeeded (默认,按需要溢出)、Always 或 Never。 提示 你能通过把每一个项的 ToolBar.OverflowMode 设置为 Never 来创建 Visual Studio 样式的自定义 ToolBar,然后添加一个拥有“_Add or Remove Buttons”头的 Menu,并且 ToolBar.- OverflowMode 设置为 Always(这样它就总是留在溢出区域)。接着把 MenuItem 都添加到这个 Menu 上,用户可以通过选中/不选 中从 ToolBar 中添加/删除相应的项。 图 4-23 ToolBar 有一个溢出区域,用来放那些在显示区域中放不下的项 自定义键盘导航 下面的 Toolbar 展示了有问题的键盘行为 如果把焦点放在 ToolBar 上并反复按 Tab,焦点会在一直从 A 到 B 到 C 到 D 到 A 到 B 这样一个循环内 停留。如果使用左或者右方向键来聚焦任何一个 MenuItem,只要一直按着方向键,焦点就会一直在 B 和 C 之间切换。 System.Windows.Input 命名空间中的 KeyboardNavigation 类定义了一些用来自定义键盘行为的附加属性。 例如,为了避免在 ToolBar 中用 Tab 键产生循环,可以把 ToolBar 上的 Keyboard- Navigation.TabNavigation 设置为 Continue(而不是 Cycle)。当在 Menu 中用箭头来进行导航时,为了避免循环,可以把 Menu 上的 KeyboardNavigation.DirectionalNavigation 设置为 Continue。 ToolBar 未用到的 Header 属性 30 更多电子书教程下载请登陆http://down.zzbaike.com/ebook 本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
分享到:
收藏