You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF MenuItem自定义子项hover效果异常,仅需子MenuItem高亮求助

问题

我有一个包含多个MenuItem的上下文菜单,其中名为“In Postfach kopieren”的MenuItem原本有大量子MenuItem。因为子项数量有时过多,我给它实现了滚动条与搜索功能:将Grid作为该MenuItem的子项,Grid包含三个元素:

  • 文本标签
  • 用于输入搜索文本的TextBox
  • 内部嵌套StackPanel的ScrollViewer(StackPanel中是用户列表MenuItem)

功能运行正常,但鼠标悬停在“In Postfach kopieren”弹出的内容区域时,整个控件会高亮,我只希望列表中的MenuItem触发高亮效果。尝试通过Grid、StackPanel等控件的鼠标进入事件禁用该效果,但没有成功。

代码如下:

var cbtnPostfachKopieren = new System.Windows.Controls.MenuItem();
cbtnPostfachKopieren.Header = "In Postfach kopieren";
cbtnPostfachKopieren.Items.Clear();
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(150) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });

var textBlock = new TextBlock();
textBlock.Text = "Search";
Grid.SetRow(textBlock, 0);
Grid.SetColumn(textBlock, 0);
grid.Children.Add(textBlock);


var textBox = new System.Windows.Controls.TextBox();
textBox.TextChanged += TextBox_TextChanged;
textBox.Width = 150;
textBox.Margin = new Thickness(10, 0, 0, 0);
textBox.Text = "Abishek";
Grid.SetRow(textBox, 0);
Grid.SetColumn(textBox, 1);
grid.Children.Add(textBox);

cbtnPostfachKopieren.Items.Add(grid);

var scrollViewer = new ScrollViewer
{
    VerticalScrollBarVisibility = ScrollBarVisibility.Visible,
    Height = 100,
    HorizontalAlignment = HorizontalAlignment.Right
};

scrollViewer.Foreground = Brushes.Brown;
Grid.SetRow(scrollViewer, 1);
Grid.SetColumn(scrollViewer, 0);
Grid.SetColumnSpan(scrollViewer, 2);
grid.Children.Add(scrollViewer);

var stackpanel = new StackPanel();
scrollViewer.Content = stackpanel;
            
for (int i = 0; i < 5; i++)
{
    System.Windows.Controls.MenuItem _btnInPostfachKopierenUserInfo = new System.Windows.Controls.MenuItem();        
    _btnInPostfachKopierenUserInfo.Header = "Abishek Kumar JAin Ravikumar";
    stackpanel.Children.Add(_btnInPostfachKopierenUserInfo);
    _btnInPostfachKopierenUserInfo.Click += _btnInPostfachKopierenUserInfo_Click;
}
解决方案

问题根源是MenuItem的容器模板会对整个子内容区域应用高亮样式,可通过以下两种方法解决:

方法一:自定义容器样式,仅让列表MenuItem触发高亮

通过修改MenuItem的ItemContainerStyle,限制高亮效果仅作用于用户列表中的子MenuItem:

首先在XAML中定义样式:

<Style x:Key="CustomMenuItemContainerStyle" TargetType="{x:Type MenuItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <Border x:Name="Border" Background="Transparent" BorderBrush="Transparent" BorderThickness="1">
                    <ContentPresenter x:Name="ContentPresenter" ContentSource="Header" Margin="2" RecognizesAccessKey="True"/>
                </Border>
                <ControlTemplate.Triggers>
                    <!-- 仅当当前项无嵌套子项时,鼠标悬停才显示高亮 -->
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}" Value="0">
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="Border" Property="Background" Value="#FFE1F5FE"/>
                            <Setter TargetName="Border" Property="BorderBrush" Value="#FF7EB4EA"/>
                        </Trigger>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

然后在代码中给父MenuItem应用该样式:

cbtnPostfachKopieren.ItemContainerStyle = (Style)FindResource("CustomMenuItemContainerStyle");

方法二:禁用容器的鼠标命中测试,仅保留必要控件的交互性

通过设置Grid的IsHitTestVisible为False,阻止它触发父MenuItem的高亮,同时单独开启TextBox和列表MenuItem的命中测试:

// 禁止Grid接收鼠标事件,避免触发父项高亮
grid.IsHitTestVisible = false;
// 确保TextBox可正常交互
textBox.IsHitTestVisible = true;
// 确保每个用户列表项可响应鼠标悬停和点击
foreach (var menuItem in stackpanel.Children.OfType<MenuItem>())
{
    menuItem.IsHitTestVisible = true;
}

这种方法更简洁,直接通过事件拦截实现需求。

内容的提问来源于stack exchange,提问作者abishekgolecha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:05:53