当前位置:  开发笔记 > 编程语言 > 正文

在显示ContextMenu之前,右键单击选择TreeView节点

如何解决《在显示ContextMenu之前,右键单击选择TreeView节点》经验,为你挑选了7个好方法。

我想在显示ContextMenu之前右键单击选择一个WPF TreeView节点.

对于WinForms,我可以使用这样的代码在上下文菜单下点击查找节点,WPF的替代方案是什么?



1> alex2k8..:

根据树的填充方式,发送方和e.Source值可能会有所不同.

其中一个可能的解决方案是使用e.OriginalSource并使用VisualTreeHelper查找TreeViewItem:

private void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject);

    if (treeViewItem != null)
    {
        treeViewItem.Focus();
        e.Handled = true;
    }
}

static TreeViewItem VisualUpwardSearch(DependencyObject source)
{
    while (source != null && !(source is TreeViewItem))
        source = VisualTreeHelper.GetParent(source);

    return source as TreeViewItem;
}


回答Louis Rhys的问题:`if(treeViewItem == null)treeView.SelectedIndex = -1`或`treeView.SelectedItem = null`.我相信要么应该工作.

2> Martin Liver..:

如果您想要一个仅限XAML的解决方案,您可以使用Blend Interactivity.

假设TreeView数据绑定到具有Boolean属性IsSelectedString属性的视图模型的分层集合Name以及命名的子项集合Children.


  
    
  
  
    
      
        
          
            
          
        
      
    
  

有两个有趣的部分:

    TreeViewItem.IsSelected属性IsSelected与视图模型上的属性绑定.将IsSelectedview-model上的属性设置为true将选择树中的相应节点.

    PreviewMouseRightButtonDown触发节点的可视部分时(在此示例a中TextBlock)IsSelected,视图模型上的属性设置为true.回到1.您可以看到在树中单击的相应节点成为选定节点.

在项目中获得Blend Interactivity的一种方法是使用NuGet包Unofficial.Blend.Interactivity.


很好的答案,谢谢!显示`i`和`ei`命名空间映射可以解决的问题以及可以找到它们的程序集会很有帮助.我假设:`xmlns:i ="http://schemas.microsoft.com/expression/ 2010/interactivity"`和`xmlns:ei ="http://schemas.microsoft.com/expression/2010/interactions"`,分别在System.Windows.Interactivity和Microsoft.Expression.Interactions程序集中找到.

3> 小智..:

使用"item.Focus();" 似乎没有100%工作,使用"item.IsSelected = true;" 确实.



4> Sean Hall..:

使用alex2k8的原创想法,正确处理来自Wieser Software Ltd的非可视化,来自Stefan的XAML,来自Erlend的IsSelected,以及我对真正制作静态方法Generic的贡献:

XAML:

 
     

C#代码背后:

void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    TreeViewItem treeViewItem = 
              VisualUpwardSearch(e.OriginalSource as DependencyObject);

    if(treeViewItem != null)
    {
        treeViewItem.IsSelected = true;
        e.Handled = true;
    }
}

static T VisualUpwardSearch(DependencyObject source) where T : DependencyObject
{
    DependencyObject returnVal = source;

    while(returnVal != null && !(returnVal is T))
    {
        DependencyObject tempReturnVal = null;
        if(returnVal is Visual || returnVal is Visual3D)
        {
            tempReturnVal = VisualTreeHelper.GetParent(returnVal);
        }
        if(tempReturnVal == null)
        {
            returnVal = LogicalTreeHelper.GetParent(returnVal);
        }
        else returnVal = tempReturnVal;
    }

    return returnVal as T;
}

编辑:以前的代码总是适用于这种情况,但在另一种情况下,当LogicalTreeHelper返回一个值时,VisualTreeHelper.GetParent返回null,因此修复了该问题.



5> Stefan..:

在XAML中,在XAML中添加PreviewMouseRightButtonDown处理程序:

    
        
    

然后像这样处理事件:

    private void TreeViewItem_PreviewMouseRightButtonDown( object sender, MouseEventArgs e )
    {
        TreeViewItem item = sender as TreeViewItem;
        if ( item != null )
        {
            item.Focus( );
            e.Handled = true;
        }
    }


它没有按预期工作,我总是将root元素作为发送者.我找到了一个类似的解决方案http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/25e113a5-6f52-4c25-974f-d58b9b689f62/这样添加的事件处理程序按预期工作.你的代码有什么变化可以接受吗?:-)

6> Anthony Wies..:

几乎是正确的,但你需要注意树中的非视觉效果(例如Run,像a ).

static DependencyObject VisualUpwardSearch(DependencyObject source) 
{
    while (source != null && source.GetType() != typeof(T))
    {
        if (source is Visual || source is Visual3D)
        {
            source = VisualTreeHelper.GetParent(source);
        }
        else
        {
            source = LogicalTreeHelper.GetParent(source);
        }
    }
    return source; 
}



7> 小智..:

我认为注册一个类处理程序应该可以解决问题.只需在app.xaml.cs代码文件中的TreeViewItem的PreviewMouseRightButtonDownEvent上注册一个路由事件处理程序,如下所示:

/// 
/// Interaction logic for App.xaml
/// 
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        EventManager.RegisterClassHandler(typeof(TreeViewItem), TreeViewItem.PreviewMouseRightButtonDownEvent, new RoutedEventHandler(TreeViewItem_PreviewMouseRightButtonDownEvent));

        base.OnStartup(e);
    }

    private void TreeViewItem_PreviewMouseRightButtonDownEvent(object sender, RoutedEventArgs e)
    {
        (sender as TreeViewItem).IsSelected = true;
    }
}


内森你好.听起来代码是全局的,会影响每个TreeView.拥有仅限本地的解决方案不是更好吗?它可能会产生副作用?
推荐阅读
赛亚兔备_393
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有