带有子菜单的可检查菜单项

发布于 2024-10-19 10:00:35 字数 608 浏览 1 评论 0原文

您可以在 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 是可以检查的,但子级别不会出现。有什么想法吗?

Can you have submenus with the top level set to checkable in WPF? I can't seem to get this to work.

<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>

Top Level 1 is checkable, but the sub levels don't appear. Any thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦魇绽荼蘼 2024-10-26 10:00:35

如果您深入研究 MenuItemControlTemplate,您会发现它根据其 Role 属性使用不同的模板。

参考:

菜单样式和模板

<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>

似乎它可以允许检查或子项目默认情况下。

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

XAML:

<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;
}

我强烈建议将此功能转换/封装为附加属性行为

If you dig into MenuItem's ControlTemplate, you will see that it uses different templates depending on it's Role property.

Reference:

Menu Styles and Templates

<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>

Seems like it can either allow checking or subitems by default.

To workaround that, use following code:

XAML:

<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>

Code behind:

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

I strongly recommend converting/encapsulating this piece of functionality into an Attached Property or a Behavior.

最好是你 2024-10-26 10:00:35

添加到 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;
} 

To add to decyclone's answer:

Since the menu will sit there still open after doing this, and if you want it to close, you can then close the menu by setting IsOpen = false on the parent contextmenu:

private void MenuItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
    (sender as MenuItem).IsChecked = !(sender as MenuItem).IsChecked; 
    ((sender as MenuItem).Parent as ContextMenu).IsOpen = false;
} 
夜清冷一曲。 2024-10-26 10:00:35

另一种方法是简单地使用复选框作为菜单项的图标:

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

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

Another approach is to simply use a CheckBox as the MenuItem's Icon:

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

In this case the user must click the CheckBox - not just anywhere on the MenuItem - in order to change the state, while clicking elsewhere will keep the default behavior of immediately opening the submenu (which may or may not be desired). Also, this allows for three-state values. In particular, this is excellent if the top level menu should function as a master switch for all its submenus, with the null state indicating that some substates are checked, and some are not. As for decyclone's answer, the menu will stay open unless further measures are taken.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文