说明:本系列基本上是《WPF揭秘》的读书笔记。在结构安排与文章内容上参照《WPF揭秘》的编排,对内容进行了总结并加入一些个人理解。
菜单也是一类Items控件。WPF中有两类菜单 – Menu与ContextMenu(上下文菜单)。
Menu(WPF)
Menu类在ItemsControl的基础上添加了IsMainMenu属性。
类似其他Items控件,Menu的项可以是任何东西,但是总是应该使用MenuItem及Separator对象。下面给一个示例:
XAML:
1 <Menu HorizontalAlignment="Left" Name="menu1" Width="200" Height="22" VerticalAlignment="Top" > 2 <MenuItem Header="_File"> 3 <MenuItem Header="_New..."></MenuItem> 4 <MenuItem Header="_Open..."></MenuItem> 5 <Separator/> 6 <MenuItem Header="Sen_d To"> 7 <MenuItem Header="My Documents"></MenuItem> 8 <MenuItem Header="Recipient"></MenuItem> 9 </MenuItem> 10 </MenuItem> 11 </Menu>
效果图(运行时):
MenuItem
MenuItem是带头的Items控件(继承自HeaderedItemControl),这种控件类似于带头的内容控件。对于MenuItem,其头实际上就是文字,如下图所示:
另外,与Button,Label相同,MenuItem使用下划线前缀支持访问键,上面的例子也使用了这个特性。
MenuItem的属性:
提示:只设置InputGestureText并不会给一个控件绑定如一个键盘快捷方式,正确的操作是将命令设置给其Command属性。同时这个命令关联到的Input Gesture会自动设置到这个属性。下图展示了这个过程:
提示:当把一个RouteUICommand赋给MenuItem的Command属性时,MenuItem的Header会被设置为Command的Text属性,显式设置Header可以重载该行为。
MenuItem的事件有Checked,Unchecked,SubmenuOpened,SubmenuClosed和Click等。
Separator
放在MenuItem中间用来分隔两个菜单项,Separator也用于ToolBar和StatusBar控件中。
技巧:让Menu垂直排列
实现这种效果,类似于我们之前做的让ListBox横排,这次要更改Menu的面板。
代码:
1 <Menu.ItemsPanel> 2 <ItemsPanelTemplate> 3 <!--StackPanel,Orientation属性默认就是水平的,无需设置--> 4 <StackPanel /> 5 </ItemsPanelTemplate> 6 </Menu.ItemsPanel>
ContextMenu(WPF)
不同于Menu,不能直接把ContextMenu放入一个元素树中,可以通过将其设置给另一个控件的ContextMenu属性(这个ContextMenu属性定义于FrameworkElement及FrameworkContentElement中,在其它控件中往往是作为附加属性出现)的方式来加载,当设置后,用户右击控件或控件有焦点的情况下按Shift+F10会显示这个菜单。示例:
XAML:
1 <Label Height="28" Name="label1" Width="120" Background="Azure"> 2 <Label.ContextMenu> 3 <ContextMenu> 4 <MenuItem Header="_File"> 5 <MenuItem Header="_New..."></MenuItem> 6 <MenuItem Header="_Open..."></MenuItem> 7 <Separator/> 8 <MenuItem Header="Sen_d To"> 9 <MenuItem Header="My Documents"></MenuItem> 10 <MenuItem Header="Recipient"></MenuItem> 11 </MenuItem> 12 </MenuItem> 13 </ContextMenu> 14 </Label.ContextMenu> 15 右击出现菜单 16 </Label>
效果图(运行时):
ContextMenu的属性:
类似于ToolTip有一个ToolTipService静态类,ContextMenu也有一个ContextMenuService来设置作用目标的属性。这个类中有许多附加属性,它们大多包装了定义于ContextMenu中的对应属性。示例:右击一个被禁用的元素时显示ContextMenu(可以使用ContextMenuService的ShowOnDisabled附加属性实现这个需求)。
XAML:
1 <Label ContextMenuService.ShowOnDisabled="True"> 2 <Label.ContextMenu> 3 … … 4 </Label.ContextMenu> 5 右击出现菜单 6 </Label>
TreeView (WPF)
TreeView控件在各种程序框架中均很常见,其用可展开和折叠的节点来分层显示数据。不同的系统主题会影响TreeView的外观。
TreeView应当使用TreeViewItem来填充,TreeViewItem也是一种带头的控件,其Header属性包含当前项,Items集合保存着子项(也是TreeViewItem)。示例:
XAML:
1 <TreeView> 2 <TreeViewItem Header="Desktop"> 3 <TreeViewItem Header="Computer"></TreeViewItem> 4 <TreeViewItem Header="Recycle"></TreeViewItem> 5 <TreeViewItem Header="MyDocument"> 6 <TreeViewItem Header="Music"></TreeViewItem> 7 <TreeViewItem Header="Pictures"></TreeViewItem> 8 </TreeViewItem> 9 </TreeViewItem> 10 </TreeView>
效果图(运行时- Windows7 Aero):
TreeViewItem的属性:
TreeViewItem的事件:
TreeViewItem支持的键盘导航:
提示:
在TreeView中要显示的用TreeViewItem 包装项(如Label,TextBlock等),这样做可以保证不会出现由于属性值继承所导致的奇怪问题。 TreeView看上去像是一个选择器(Selector),其不是由Selector继承,由于TreeView项不能使用简单的整数索引来标识。TreeView定义了自己的SelectedItem以及SelectedValue(没有定义SelectedIndex),还有SelectedItemChanged事件(传给事件处理函数的参数会包括OldValue与NewValue项 – TreeView一次处理一个选择项)
ToolBar(WPF)
使用ToolBar控件可以对许多小的按钮或其他控件进行分组,可以将菜单中的功能等以这样一种更容易访问的方式来展示。先展示一个ToolBar的示例:
XAML:
1 <ToolBar VerticalAlignment="Top" Height="26" > 2 <Button> 3 <Image Source="copy1.gif"/> 4 </Button> 5 <Separator/> 6 <ToggleButton> 7 <Image Source="bold.gif"/> 8 </ToggleButton> 9 <ToggleButton> 10 <Image Source="italic.gif"/> 11 </ToggleButton> 12 <ToggleButton> 13 <Image Source="underline.gif"/> 14 </ToggleButton> 15 <Separator/> 16 <ToggleButton> 17 <Image Source="left.gif"/> 18 </ToggleButton> 19 <ToggleButton> 20 <Image Source="right.gif"/> 21 </ToggleButton> 22 <ToggleButton> 23 <Image Source="justify.gif"/> 24 </ToggleButton> 25 <Separator/> 26 <Label>Zoom</Label> 27 <ComboBox SelectedIndex="0"> 28 <ComboBoxItem>100%</ComboBoxItem> 29 <ComboBoxItem>75%</ComboBoxItem> 30 <ComboBoxItem>50%</ComboBoxItem> 31 <ComboBoxItem>25%</ComboBoxItem> 32 </ComboBox> 33 <Separator/> 34 <Button> 35 <Image Source="superscript.gif"/> 36 </Button> 37 <Button> 38 <Image Source="subscript.gif"/> 39 </Button> 40 </ToolBar>
效果图(运行时):
ToolBar中的项可以是任意类型的内容,ToolBar重载了项的默认样式,所以放在ToolBar中的按钮,ComboBox不是我们常见的样子,分隔条也变成了垂直线这样我们常见的工具条的样式。
ToolBar通常被放置在ToolBarTray这个FrameworkElement中(虽然其可以被放置在元素树的任何位置),放置的方式是作为ToolBarTray的ToolBars属性来设置。示例代码:
1 <ToolBarTray> 2 <ToolBarTray.ToolBars> 3 <ToolBar> 4 … … 5 </ToolBar> 6 </ToolBarTray.ToolBars> 7 </ToolBarTray>
ToolBarTray的属性:
ToolBar的属性:
StatusBar(WPF)
StatusBar通常处在窗口的底部用于显示状态信息,其将它的子元素横排。先看一个示例:
XAML:
1 <StatusBar Height="26"> 2 <Label>StatusBar Item</Label> 3 <Separator/> 4 <Label>Zoom</Label> 5 <ComboBox SelectedIndex="0"> 6 <ComboBoxItem>100%</ComboBoxItem> 7 <ComboBoxItem>75%</ComboBoxItem> 8 <ComboBoxItem>50%</ComboBoxItem> 9 <ComboBoxItem>25%</ComboBoxItem> 10 </ComboBox> 11 <Separator/> 12 <Button> 13 <Image Source="justify.gif"/> 14 </Button> 15 </StatusBar>
不同于ToolBar,默认情况下StatusBar只为Separator提供了一个模版,以控制Separator被渲染为垂直线。
另外,StatusBar隐式的将其中的项包装在StatusBarItem中,你可以显示的进行包装,如下示例:
1 <StatusBar> 2 <StatusBarItem> 3 <Label>StatusBar Item</Label> 4 </StatusBarItem> 5 </StatusBar>
这样你就可以使用部分布局控件提供的附加属性来自定义这些项的位置。
技巧:将StatusBar按比例分割,并可以自动适应容器长度变化。
这个问题的解决办法仍然是前文用过的自定义控件的模版,可以用Grid作为StatusBar的ItemPanel,并通过配置Grid的列来实现这个效果。
本文完
参考:
《WPF揭秘》