带子菜单的可检查MenuItem

时间:2011-02-25 02:12:35

标签: wpf menuitem

您是否可以在WPF中设置顶级设置为可检查的子菜单?我似乎无法让这个工作。

<Window.ContextMenu>
    <ContextMenu>
        <MenuItem Header="Top Level 1" IsCheckable="True" IsChecked="True">
            <MenuItem Header="Sub Level" />
            <MenuItem Header="Sub Level" />
        </MenuItem>
        <MenuItem Header="Top Level 2">
            <MenuItem Header="Sub Level" />
            <MenuItem Header="Sub Level" />
        </MenuItem>
    </ContextMenu>
</Window.ContextMenu>

顶级1是可检查的,但子级别不会出现。有什么想法吗?

3 个答案:

答案 0 :(得分:6)

如果你深入研究MenuItem的{​​{1}},你会看到它使用不同的模板,具体取决于它的ControlTemplate属性。

参考:

Menu Styles and Templates

Role

似乎它可以默认允许检查或子项。

要解决此问题,请使用以下代码:

XAML:

<Style x:Key="{x:Type MenuItem}"
       TargetType="{x:Type MenuItem}">
  <Setter Property="OverridesDefaultStyle"
          Value="True" />
  <Style.Triggers>
    <Trigger Property="Role"
             Value="TopLevelHeader">
      <Setter Property="Template"
              Value="{StaticResource {x:Static MenuItem.TopLevelHeaderTemplateKey}}" />
      <Setter Property="Grid.IsSharedSizeScope"
              Value="true" />
    </Trigger>
    <Trigger Property="Role"
             Value="TopLevelItem">
      <Setter Property="Template"
              Value="{StaticResource {x:Static MenuItem.TopLevelItemTemplateKey}}" />
    </Trigger>
    <Trigger Property="Role"
             Value="SubmenuHeader">
      <Setter Property="Template"
              Value="{StaticResource {x:Static MenuItem.SubmenuHeaderTemplateKey}}" />
    </Trigger>
    <Trigger Property="Role"
             Value="SubmenuItem">
      <Setter Property="Template"
              Value="{StaticResource {x:Static MenuItem.SubmenuItemTemplateKey}}" />
    </Trigger>
  </Style.Triggers>
</Style>

代码背后:

<ContextMenu>
    <MenuItem Header="Top Level 1" 
              Mouse.PreviewMouseUp="MenuItem_MouseLeftButtonUp">
        <MenuItem Header="Sub Level" />
        <MenuItem Header="Sub Level" />
    </MenuItem>
    <MenuItem Header="Top Level 2">
        <MenuItem Header="Sub Level" />
        <MenuItem Header="Sub Level" />
    </MenuItem>
</ContextMenu>

我强烈建议将此功能转换/封装为private void MenuItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { (sender as MenuItem).IsChecked = !(sender as MenuItem).IsChecked; } Attached Property

答案 1 :(得分:0)

添加到decyclone的答案:

由于菜单会在执行此操作后仍处于打开状态,如果您希望它关闭,您可以通过在父上下文菜单上设置IsOpen = false来关闭菜单:

private void MenuItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
    (sender as MenuItem).IsChecked = !(sender as MenuItem).IsChecked; 
    ((sender as MenuItem).Parent as ContextMenu).IsOpen = false;
} 

答案 2 :(得分:0)

另一种方法是简单地使用CheckBox作为MenuItem的图标:

<MenuItem>
    <MenuItem.Icon>
        <CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding MyCheckProperty}"/>
    </MenuItem.Icon>
    <MenuItem Header="Item1"/>
    <MenuItem Header="Item2"/>
</MenuItem>

在这种情况下,用户必须单击CheckBox(不仅在MenuItem上的任何位置)以更改状态,而单击其他位置将保留立即打开子菜单的默认行为(可能需要也可能不需要)。而且,这允许三态值。特别是,如果顶级菜单应充当其所有子菜单的主开关,并且空状态指示已选中某些子状态,而未选中某些子状态,则这非常好。至于旋风的答案,除非采取进一步措施,否则菜单将保持打开状态。