忽略TreeviewItem上的PreviewMouseButtonDown中的父级

时间:2014-07-30 21:15:43

标签: c# wpf events treeviewitem routed-events

我有一个树视图,我试图实现拖放功能。

<TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
         <EventSetter Event="TreeViewItem.PreviewMouseLeftButtonDown" Handler="PreviewMouseLeftButtonDown" />
    </Style>
</TreeView.ItemContainerStyle>

然后我在后面的代码中有一个事件来处理点击,然后开始拖动:

void PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (sender is TreeViewItem)
    {
       //clone the tree item, create an adorner, apply adorner
       //doDragDrop
    }
}

我的问题是,因为PreviewMouseLftButtonDown是使用隧道策略的路由事件,当在treenode项目上单击鼠标时,我首先获得根节点。我对根节点不感兴趣,只对叶节点感兴趣。我的结构是这样的:

HeaderNodeObject
   |_LeafnodeObject
   |_LeafNodeOject

所以在我的事件中我基本上不需要做任何事情,只要发送者treeViewItem是HeaderNodeObject就继续。但是我该如何判断它是什么?发件人作为treeViewItem进来,我不知道如何判断它所拥有的对象是什么。

4 个答案:

答案 0 :(得分:1)

上述解决方案仅适用于leafs,我必须为TreeView执行此操作,我希望在树中的任何节点上处理PreviewMouseLeftDown事件。我终于通过忽略孩子鼠标悬停的所有节点的事件来解决它。像这样:

var treeViewItem = sender as TreeViewItem;
if (treeViewItem.Items.OfType<TreeViewItem>().All(item => !item.IsMouseOver))
{
    //do my stuff
}

一种hackish解决方案,但我找不到更好的,至少它完成了工作......

答案 1 :(得分:1)

您应该可以使用e.Source as TreeViewItem来检索已点击的项目。您可以针对sender进行检查,以确认您只在到达来源时处理该事件。

这会导致仅针对所点击的项目处理事件:

void PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (e.Source is TreeViewItem item && sender == item)
         /* do something */;
}

但是,请注意,直接使用事件意味着如果项目的任何部分收到鼠标按下事件(包括扩展按钮),您将收到该事件。因此,请注意 * not * 设置e.Handled = true,以免您阻止用户切换扩展等。

答案 2 :(得分:0)

我只是通过检查发件人的itemsource是否为空来简单地解决了这个问题。如果它的null表示它的叶节点:

if (sender is TreeViewItem)
{
   Item = sender as TreeViewItem;

    //make sure we have a leaf node, if we dont just move on.
    if (Item.ItemsSource == null)
    {
     //do my stuff
    }
}

答案 3 :(得分:0)

不会将此称为重复答案,但只会提及ØysteinKolsrud的答案是正确的,因为这可能没有数据绑定。我没有足够的声誉,否则我只会评论和投票,但“用户”的答案只适用于树上的叶子,而Øystein的答案适用于树上的所有节点,包括所有叶子节点。 / p>

我的案例涉及通过一个相当浅(但人口密集)的递归填充的“工作项”树。我使用TreeView来显示工作流层次结构,其中所选节点将引发从TreeViewItem的标头捕获Work ID文本的事件,因此我可以以有意义的方式使用该WorkID。当我希望这不仅仅是根或只是第一级孩子(留下根)时,Øystein的回答就是我必须走的路。绝对是hackish,但绝对有效。

我以前的所有代码(除了他的条件检查)之前都有。我所要做的只是包括他的支票,一切都按照我最初的预期进行。

只是想分享这个工作的真实例子并验证他的工作。这种情况就像一个魅力,拯救了我的屁股。再次感谢,ØysteinKolsrud!!

     private void TreeItem_Selected(object sender, RoutedEventArgs e)
    {
        TreeViewItem workItem = sender as TreeViewItem;
        if(workItem.Items.OfType<TreeViewItem>().All(item => !item.IsMouseOver))
        {
            string workItemHeader = workItem.Header.ToString();
            string stopAt = "-";
            currentWorkIDToEdit = workItemHeader.Substring(0, workItemHeader.IndexOf(stopAt));
            workItemToEdit.Content = "Work Item To Edit: " + currentWorkIDToEdit + " ";
        }
    }