在WPF中弹出右键菜单时判断鼠标是否选中该项
2016-07-25 11:10
344 查看
和上篇在WPF的TreeView中实现右键选定一样,这仍然是一个右键菜单的问题:
这个需求是在一个实现剪贴板的功能的时候遇到的:在弹出右键菜单时,如果菜单弹出位置在ListViewItem中时,我们认为这项已经被选中,可以使用剪贴板功能。
当菜单弹出位置在ListView的空白处时,我们一般认为没有项被选中,此时是不应该使能剪贴板功能的。
但是这个时候,该项仍然是选中的。不能通过Item的IsSelected的属性来区分这两种情况。这样,就需要我们加一个判断鼠标是否在所选的节点上的函数。实现这个功能的方式有如下两种:
方法1:响应ListView的PreviewMouseRightButtonDown事件,在其中判断是否有节点被选中。还是直接上代码吧:
bool isItemSelected = false;
private void ListView_PreviewMouseRightButtonDown(object sender,
MouseButtonEventArgs e)
{
object item = GetElementFromPoint((ItemsControl)sender, e.GetPosition((ItemsControl)sender));
isItemSelected = (item != null);
}
private object GetElementFromPoint(ItemsControl itemsControl,
Point point)
{
UIElement element = itemsControl.InputHitTest(point)
as UIElement;
while (element !=
null)
{
if (element == itemsControl)
return null;
object item = itemsControl.ItemContainerGenerator.ItemFromContainer(element);
if (!item.Equals(DependencyProperty.UnsetValue))
return item;
element = (UIElement)VisualTreeHelper.GetParent(element);
}
return null;
}
这个其实就是一个命中测试的方面的问题,代码还是比较基础的,也没有什么需要解释的地方,但写起来还是有点麻烦。
方法2:同时响应ListView的PreviewMouseRightButtonDown事件和TreeViewItem的PreviewMouseRightButtonDown事件。
当鼠标点击在ListViewItem上时:发生的事件顺序为 ListView_MouseDown 、ListViewItem_MouseDown。
当鼠标点击在ListView外时:发生的事件仅为 ListView_MouseDown 。
因此,只要在ListView_MouseDown 中设置isItemSelected = false,在ListViewItem_MouseDown中设置isItemSelected =
true即可。由于非常简单,就不附代码了。
使用上面的两种方法后,就可以直接在剪切复制命令的CanExecute函数中通过isItemSelected来判断是否该使能剪切复制命令了。
另外,这两方法是针对ItemsControl类型的控件的,也就是说,在TreeView或ListBox等控件中也可以使用,如果把它们封装一下就更方便了。
这个需求是在一个实现剪贴板的功能的时候遇到的:在弹出右键菜单时,如果菜单弹出位置在ListViewItem中时,我们认为这项已经被选中,可以使用剪贴板功能。
当菜单弹出位置在ListView的空白处时,我们一般认为没有项被选中,此时是不应该使能剪贴板功能的。
但是这个时候,该项仍然是选中的。不能通过Item的IsSelected的属性来区分这两种情况。这样,就需要我们加一个判断鼠标是否在所选的节点上的函数。实现这个功能的方式有如下两种:
方法1:响应ListView的PreviewMouseRightButtonDown事件,在其中判断是否有节点被选中。还是直接上代码吧:
bool isItemSelected = false;
private void ListView_PreviewMouseRightButtonDown(object sender,
MouseButtonEventArgs e)
{
object item = GetElementFromPoint((ItemsControl)sender, e.GetPosition((ItemsControl)sender));
isItemSelected = (item != null);
}
private object GetElementFromPoint(ItemsControl itemsControl,
Point point)
{
UIElement element = itemsControl.InputHitTest(point)
as UIElement;
while (element !=
null)
{
if (element == itemsControl)
return null;
object item = itemsControl.ItemContainerGenerator.ItemFromContainer(element);
if (!item.Equals(DependencyProperty.UnsetValue))
return item;
element = (UIElement)VisualTreeHelper.GetParent(element);
}
return null;
}
这个其实就是一个命中测试的方面的问题,代码还是比较基础的,也没有什么需要解释的地方,但写起来还是有点麻烦。
方法2:同时响应ListView的PreviewMouseRightButtonDown事件和TreeViewItem的PreviewMouseRightButtonDown事件。
当鼠标点击在ListViewItem上时:发生的事件顺序为 ListView_MouseDown 、ListViewItem_MouseDown。
当鼠标点击在ListView外时:发生的事件仅为 ListView_MouseDown 。
因此,只要在ListView_MouseDown 中设置isItemSelected = false,在ListViewItem_MouseDown中设置isItemSelected =
true即可。由于非常简单,就不附代码了。
使用上面的两种方法后,就可以直接在剪切复制命令的CanExecute函数中通过isItemSelected来判断是否该使能剪切复制命令了。
另外,这两方法是针对ItemsControl类型的控件的,也就是说,在TreeView或ListBox等控件中也可以使用,如果把它们封装一下就更方便了。
相关文章推荐
- webApplicationContext 与servletContext
- 新建一个module形式的第三方library的通用步骤是:
- STL算法大全
- HTML5——离线应用程序
- 已知前序中序求后序
- 整理:<cctype>(<ctype.h>)
- linux 查看 *.a *.so 符号表(zt)
- 时光倒流程序设计-AlloyTicker
- Qt中forward declaration of struct Ui::xxx的解决
- 靠谱的分布式锁实现
- 局部变量与成员变量的存放
- Android跑马灯实现
- android 开发工具—AndroidStudio获取SHA1值
- Jquery 某效果展示
- POJ 2352 Star (树状数组)
- android中的MVP模式
- java统计abacbacdadbc中的每个字母出现的次数,输出格式是:a(4)b(3)c(3)d(2)
- Linux日志分析的实战专题
- 项目中学到SQL语句中的一些常用技巧及函数
- php下载代码