WPF小技巧——ListView和TreeView的右键菜单(ContextMenu)点的谁

ListView和TreeView大家都知道,配合ItemTemplate可以做出很好看的列表。如果需要其中某一项进行操作,首先想到的肯定是给ItemTemplate添加右键菜单,比如说把这段XML代码放到ListView的里面:

<ListView.ContextMenu>
    <ContextMenu>
        <MenuItem x:Name="ContextMenu1" Header="菜单项" Click="ContextMenu1_Click"/>
    </ContextMenu>
</ListView.ContextMenu>

可是WPF有一个极为愚蠢的设定,右键的时候并不是默认选定当前项的,那么从ListView的SelectedItem等相关属性一概是看不出用户对着哪一项点的右键。并且菜单事件的sender就只能看到ContextMenu自己,也看不到其他有用信息。于是用户必须先左键选中,再右键菜单,简直愚蠢透顶。

我参考的方法是这篇:在WPF的TreeView中实现右键选定

给Item添加PreviewMouseRightButtonDown事件,就是鼠标右键点下瞬间:

<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <EventSetter Event="ListViewItem.PreviewMouseRightButtonDown" Handler="ListViewItem_PreviewMouseRightButtonDown"/>
    </Style>
</ListView.ItemContainerStyle>

然后用如下代码让右键点下瞬间选中当前项:

private void ListViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    var ListViewItem = VisualUpwardSearch<ListViewItem>(e.OriginalSource as DependencyObject) as ListViewItem;
    if (ListViewItem != null)
    {
        ListViewItem.Focus();
        e.Handled = true;
    }
}

static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
    while (source != null && source.GetType() != typeof(T))
    source = VisualTreeHelper.GetParent(source);
    return source;
}

但是年代久远或者其他什么原因,很遗憾这段代码并没有实现预期功能,右键菜单还是找不到被点击对象。不过在调试过程中发现了一点,就是强制转换的ListViewItem的确是右键点击的当前项,于是方案如下:

1、准备一个全局变量用来保存ListViewItem或是它所绑定的DataContext,因为很多时候需要的其实是当前项的数据而已;比如说我们用的是DataVar类型的变量data,稍微修改一下前面的代码:

private void ListViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    var ListViewItem = VisualUpwardSearch<ListViewItem>(e.OriginalSource as DependencyObject) as ListViewItem;
    if (ListViewItem != null)
    {
        data = ListViewItem.DataContext as DataVar;
        ListViewItem.Focus();
        e.Handled = true;
    }
}

static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
    while (source != null && source.GetType() != typeof(T))
    source = VisualTreeHelper.GetParent(source);
    return source;
}

2、ContextMenu的代码照样写,改为从全局变量data获取当前项的信息:

private void ContextMenu1_Click(object sender, RoutedEventArgs e)
{
            if (data is null) return;
            //然后该干什么干什么

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值