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

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


    
        
    

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

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

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


    

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

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

static DependencyObject VisualUpwardSearch(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(e.OriginalSource as DependencyObject) as ListViewItem;
    if (ListViewItem != null)
    {
        data = ListViewItem.DataContext as DataVar;
        ListViewItem.Focus();
        e.Handled = true;
    }
}

static DependencyObject VisualUpwardSearch(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;
            //然后该干什么干什么

}

你可能感兴趣的:(日常,wpf,c#)