【WPF】右键菜单ContextMenu可点击区域太小的问题

简介: 原文:【WPF】右键菜单ContextMenu可点击区域太小的问题问题描述 正常使用右键菜单ContextMenu时,如果菜单项是不变的,可以直接在XAML中写死,如下是给一个Button按钮添加了右键菜单功能。
原文: 【WPF】右键菜单ContextMenu可点击区域太小的问题

问题描述

正常使用右键菜单ContextMenu时,如果菜单项是不变的,可以直接在XAML中写死,如下是给一个Button按钮添加了右键菜单功能。

<Button Content="Test" Width="100" Height="30">
    <Button.ContextMenu>
        <ContextMenu>
            <MenuItem Header="1"/>
            <MenuItem Header="1123"/>
            <MenuItem Header="11234134532"/>
            <MenuItem Header="1234532"/>
            <MenuItem Header="1234"/>
            <MenuItem Header="13245324532543253"/>
        </ContextMenu>
    </Button.ContextMenu>
</Button>

此时整个MenuItem菜单项都是可以响应点击的。

然而项目中通常右键菜单项MenuItem的内容是不固定的,是通过ItemsSource绑定了集合。集合使用的数据内容是可以动态修改的,在XAML中只是写数据模板ItemTemplate。代码改造一下如下。

XAML:ItemSource绑定列表DataList,MenuItem中显示的是DataList集合中的每个自定义对象的Num属性。

<Button Content="Test" Width="100" Height="30">
    <Button.ContextMenu>
        <ContextMenu ItemsSource="{Binding DataList, Mode=TwoWay}">
            <ContextMenu.ItemTemplate>
                <DataTemplate>
                    <MenuItem Header="{Binding Num}"
                          Command="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.YourCommand}" 
                          CommandParameter="{Binding RelativeSource={x:Static RelativeSource.Self}}"/>
                </DataTemplate>
            </ContextMenu.ItemTemplate>
        </ContextMenu>
    </Button.ContextMenu>
</Button>

自定义的实体类Student.cs。

public class Student
{
    public string Num { get; set; }
    public int Age { get; set; }
}

ViewModel:定义DataList集合。

private ObservableCollection<Student> dataList;
public ObservableCollection<Student> DataList
{
    get { return dataList; }
    set { dataList = value; }
}

给DataList填充数据。

DataList = new ObservableCollection<Student>();
DataList.Add(new Student() { Num = "12", Age = 10});
DataList.Add(new Student() { Num = "12213", Age = 10 });
DataList.Add(new Student() { Num = "1212", Age = 10 });
DataList.Add(new Student() { Num = "2", Age = 10 });
DataList.Add(new Student() { Num = "112341242134122", Age = 10 });
DataList.Add(new Student() { Num = "123452342", Age = 10 });

运行后即可发现问题。

仔细观察上图运行效果,每个菜单项是嵌套在条目内部的,只有点击到中间深色区域才能触发菜单项的点击事件!点击左右两端浅色部分也能使菜单项关闭,但不会触发菜单项的点击事件!

 

解决方案

最初的想法是给内部被嵌套的MenuItem改样式,改为Padding=0应该就能使其扩大到紧贴整个条目区域。

<Button Content="Test" Width="100" Height="30">
    <Button.ContextMenu>
        <ContextMenu ItemsSource="{Binding DataList, Mode=TwoWay}">
            <ContextMenu.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Padding" Value="-33,0,-63,0"/>
                </Style>
            </ContextMenu.ItemContainerStyle>
            <ContextMenu.ItemTemplate>
                <DataTemplate>
                    <MenuItem Header="{Binding Num}" 
                          Command="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.YourCommand}" 
                          CommandParameter="{Binding RelativeSource={x:Static RelativeSource.Self}}"/>
                </DataTemplate>
            </ContextMenu.ItemTemplate>
        </ContextMenu>
    </Button.ContextMenu>
</Button>

通过ContextMenu.ItemContainerStyle设置样式的Padding属性后,看上去菜单项已经覆盖了整个条目,但点击时依然是左右两端无法响应点击事件,只有中间部分能响应到!(测试的点击事件已被绑定到YourCommand命令中,此处已省略)

 

谷歌一下,看看别人是怎么处理该问题的。

参考:

  1. https://social.msdn.microsoft.com/Forums/vstudio/en-US/188e6bad-352a-4e7d-a3bb-0a88f7760529/datatemplate-can-not-access-menuitemclick-attribute?forum=wpf
  2. https://stackoverflow.com/questions/44763405/c-sharp-wpf-contextmenu-menuitem-does-not-react-to-click

上面第一篇文章中,老外的意见是不要在ItemTemplate中嵌套MenuItem,改为嵌套TextBlock。试了一下发现没用。。

根据第二篇中的回复,改为不用DataTemplate,完全在ContextMenu.ItemContainerStyle中设置菜单项的属性,试用后生效了。

<Button Content="Test" Width="100" Height="30">
    <Button.ContextMenu>
        <ContextMenu ItemsSource="{Binding DataList, Mode=TwoWay}" Padding="0">
            <!-- 消除ItemTemplate造成的内部MenuItem嵌套,导致左右两端无法响应点击的问题 -->
            <ContextMenu.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Header" Value="{Binding Num}"/>
                    <Setter Property="Command" Value="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.YourCommand}"/>
                    <Setter Property="CommandParameter" Value="{Binding RelativeSource={x:Static RelativeSource.Self}}"/>
                </Style>
            </ContextMenu.ItemContainerStyle>
        </ContextMenu>
    </Button.ContextMenu>
</Button>

此时MenuItem菜单项覆盖了整个条目,且点击左右两端都能触发点击事件了!

 

目录
相关文章
|
C#
WPF 左键单击弹出菜单 ContextMenu
原文:WPF 左键单击弹出菜单 ContextMenu WPF中的ContextMenu在XAML中可直接做出来,但是仅限于右键弹出菜单,如果需要添加左键弹出功能,只需要在事件中添加Click事件 XMAL代码如下 ...
2887 0
|
数据可视化 C# DataX
WPF 的 ElementName 在 ContextMenu 中无法绑定成功?试试使用 x:Reference!
原文:WPF 的 ElementName 在 ContextMenu 中无法绑定成功?试试使用 x:Reference! 版权声明:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
1263 0
|
前端开发 C#
WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参
原文:WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参 ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataContext,所以如果要绑定父级的DataContext,直接DataContext=“{Bind...
3443 0
|
C#
WPF ContextMenu的使用
给ContextMenu菜单添加图片 ...
1069 0
|
6月前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
389 0
|
6月前
|
C#
浅谈WPF之装饰器实现控件锚点
使用过visio的都知道,在绘制流程图时,当选择或鼠标移动到控件时,都会在控件的四周出现锚点,以便于修改大小,移动位置,或连接线等,那此功能是如何实现的呢?在WPF开发中,想要在控件四周实现锚点,可以通过装饰器来实现,今天通过一个简单的小例子,简述如何在WPF开发中,应用装饰器,仅供学习分享使用,如有不足之处,还请指正。
142 1
|
3月前
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
3月前
|
C# 开发者 Windows
一款基于Fluent设计风格、现代化的WPF UI控件库
一款基于Fluent设计风格、现代化的WPF UI控件库
|
3月前
|
C# Windows
WPF中如何使用HandyCotrol控件库
WPF中如何使用HandyCotrol控件库
195 1
|
3月前
|
C# 前端开发 UED
WPF数据验证实战:内置控件与自定义规则,带你玩转前端数据验证,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,数据验证是确保输入正确性的关键环节。前端验证能及时发现错误,提升用户体验和程序可靠性。本文对比了几种常用的WPF数据验证方法,并通过示例展示了如何使用内置验证控件(如`TextBox`)及自定义验证规则实现有效验证。内置控件结合`Validation`类可快速实现简单验证;自定义规则则提供了更灵活的复杂逻辑支持。希望本文能帮助开发者更好地进行WPF数据验证。
116 0