2009-09-15 78 views
3

我有一个WPF TreeView子级项目。我使用HierarchicalDataTemplate作为顶级项目,所以子项目绑定到后台数据列表。拖放到一个TreeView,找到索引插入被删除项目的位置

当我做拖放操作时,我想找出目标列表中新项目应该到达的位置。我已经打破了场景分为以下几个情况:

  1. 我对目标的空白部分TreeView
  2. 我徘徊于或接近顶层TreeViewItem S的一个(丢弃项目必须去列表的后面)
  3. 我悬停在其中一个子项目上,在这种情况下,丢弃的项目必须移到当前项目的前面或后面,具体取决于我是悬停在上面还是悬停在上面或项目的下半部分。

我的问题是,我怎么知道我徘徊在哪个TreeViewItem?我如何知道它是父母型还是儿童型TreeViewItem? (他们有不同的DataContext数据类型)我应该做某种类型的测试吗?我如何知道哪个顶级项目拥有当前正在悬停的子项目?

回答

6

在尝试了一堆东西之后,我想我已经想出了一个办法来做到这一点。 DragOverDrop事件向您发送DragEventArgs参数。你用它来做点击测试。如果你击中了,你不可能直接击中你想要的物品。相反,你将会碰到构成项目模板一部分的东西。要访问您感兴趣的TreeViewItems,您可以尝试并沿着Visual Tree走。

在这个例子中的顶层TreeViewItems被绑定到GroupItem实例和子节点被绑定到DragItems实例。 tv是TreeView元素本身的名称。在这段代码中,假定我会找到它,因为事件处理程序是在这个元素上定义的。

我创建了以下遍历树的代码。

private void FindDropTarget(
     out TreeViewItem pGroupingNode, 
     out TreeViewItem pItemNode, 
     DragEventArgs pDragEventArgs) 
    { 
     pItemNode = null; 
     pGroupingNode = null; 

     DependencyObject k = VisualTreeHelper.HitTest(tv, pDragEventArgs.GetPosition(tv)).VisualHit; 

     while (k != null) 
     { 
      if (k is TreeViewItem) 
      { 
       TreeViewItem treeNode = k as TreeViewItem; 
       if (treeNode.DataContext is GroupItem) 
       { 
        pGroupingNode = treeNode; 
       } 
       else if (treeNode.DataContext is DragItems) 
       { 
        pItemNode = treeNode; 
       } 
      } 
      else if (k == tv) 
      { 
       Console.WriteLine("Found treeview instance"); 
       return; 
      } 

      k = VisualTreeHelper.GetParent(k); 
     } 
    } 

像这样消耗它。注意检查IsVisible这是很重要的:

private void tv_DragOver(object sender, DragEventArgs e) 
    { 
     TreeViewItem groupingNode, itemNode; 
     FindDropTarget(out groupingNode, out itemNode, e); 

     GroupItem groupingData = (groupingNode != null ? groupingNode.DataContext as GroupItem : null); 
     DragItems dragItem = (itemNode != null && itemNode.IsVisible ? itemNode.DataContext as DragItems : null); 

     Console.WriteLine("Hovering ..."); 
     Console.WriteLine(
      "Grouping Node = {0}, Item Node = {1}", 
      groupingData != null ? groupingData.Title : "null", 
      dragItem != null ? dragItem.Id : "null"); 
    } 

如果你想给某种要将项目下降视觉指示的,可以考虑使用装饰器就像Bea Stollnitz explains here。你也可以考虑改变Bound数据类的某种价值(比如有一个IsHovering属性,它可以通过数据绑定高亮显示该物品)

3

这是一个更简单更简洁的方式,感谢Pieter Breed的方向。

private void Tree_DragOver(object sender, DragEventArgs e) { 
TreeViewItem treeViewItem = FindAncestor<TreeViewItem>((DependencyObject)e.OriginalSource); 
if (treeViewItem != null) { 
    treeViewItem.Background = Brushes.Blue; 
} 
} 
private void Tree_DragLeave(object sender, DragEventArgs e) { 
TreeViewItem treeViewItem = FindAncestor<TreeViewItem>((DependencyObject)e.OriginalSource); 
if (treeViewItem != null) { 
    treeViewItem.Background = Brushes.White; 
} 
} 
private static T FindAncestor<T>(DependencyObject current) where T : DependencyObject { // Search the VisualTree for specified type 
while (current != null) { 
    if (current is T) { 
     return (T)current; 
    } 
    current = VisualTreeHelper.GetParent(current); 
} 
return null; 
} 
相关问题