如何使用加速器在WPF中创建自定义MenuHeader?

时间:2020-03-05 18:52:22  来源:igfitidea点击:

我想在WPF中创建一些自定义MenuHeader,以便在菜单项中包含(例如)图标和文本。

通常使用MenuItems,如果用纯文本填充"标题"字段,则可以使用下划线添加加速器。例如,_File

但是,如果我想放入UserControl,我相信此功能会中断,我将如何执行以下操作?

<Menu>
<MenuItem>
    <MenuItem.Header>
    <UserControl>
        <Image Source="..." />
        <Label Text="_Open" />
    </UserControl>
    </MenuItem.Header>
</MenuItem>
...

解决方案

回答

问题是我们将图像放置在MenuHeader内容的内部,这意味着我们将丢失加速键。如果我们只是想在菜单标题中添加图像,请执行以下操作。

<MenuItem Header="_Open">
  <MenuItem.Icon>
    <Image Source="images/Open.png"/>
  </MenuItem.Icon>
</MenuItem>

如果要进一步自定义外观,请修改菜单的控件模板和样式。根据经验,设置菜单和菜单项的样式要比设置其他WPF控件的样式困难得多。

回答

@ a7an:啊,我之前没有注意到Icon属性。那是一个好的开始。

但是,我特别想在某些MenuItems中添加一个额外的"按钮",以便可以具有" Pin"功能(有关功能概念,请参阅Office 2007中最近加载的文档列表)。

由于还需要编写代码,因此我可能需要对控件进行子类化并为按钮添加代码吗? (不怕搞砸MenuItem模板,已经必须做一次,如果必须的话,我会再次做!))

回答

我认为Icon属性适合需求。
但是,要回答原始问题,可以在编写菜单项的内容时保留Accelerator功能。如果我们在MenuItem中嵌套了内容,则需要像下面的第一个一样显式定义AccessText属性。使用内联表单时,将自动进行处理。

<Menu> 
   <MenuItem>
      <MenuItem.Header>
        <StackPanel Orientation="Horizontal">
          <Image Source="Images/Open.ico" />      
          <AccessText>_Open..</AccessText>
        </StackPanel>
      </MenuItem.Header>
    </MenuItem>
    <MenuItem Header="_Close" />
   </Menu>

回答

首先考虑一下,我们会认为Icon属性只能包含图像。但是它实际上可以包含任何东西!当我以编程方式尝试将Image属性直接设置为具有图像路径的字符串时,偶然发现了这一点。结果是它没有显示图像,而是路径的实际文本!然后,我发现必须首先创建一个Image元素并将其设置为Icon属性。这使我认为Image属性只是菜单左侧图标区域中的任何内容容器,而我是对的。我试图在那儿放一个按钮,它起作用了!

这将在菜单项的"图标"区域中显示一个带有文本" i"的按钮。当我们单击按钮时,将触发Button_Click事件(单击按钮时不会触发LanguageMenu_Click)。

<MenuItem Name="LanguageMenu" Header="_Language" Click="LanguageMenu_Click">
  <MenuItem.Icon>
    <Button Click="Button_Click">i</Button>
  </MenuItem.Icon>
</MenuItem>

这导致不必为图标制作图像,而是使用带有符号字体的文本来显示简单的"图标"。下面的示例使用Wingdings字体,其中包含一个软盘符号。字体中的这个符号被映射到字符" <",在XAML中具有特殊含义,因此我们必须使用编码版本" <"。这像梦一样运作!下面在菜单项上将软盘符号显示为图标:

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
  <MenuItem.Icon>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" 
           FontFamily="Wingdings">&lt;</Label>
  </MenuItem.Icon>                
</MenuItem>