绑定到集合时使用WPF树视图的正确方法

时间:2010-09-24 17:34:28

标签: c# wpf

对于我正在进行的项目,我需要使用拖放重新排序创建树视图。在搞乱实际项目之前,我在一个单独的项目中将treeview子类化,并为Drop,DragOver,MouseMove和DragLeave事件添加了处理程序,并在必要时实现它们。拖放重新排序适用于副项目,因为我设置了这样,每个TreeViewItem将我感兴趣的项目存储在Header属性中。

以下是一些代码:

       void MultiSelectTreeView_Drop(object sender, System.Windows.DragEventArgs e)
    {
        if (e.Data.GetDataPresent(typeof(TreeViewItem)))
        {
            TreeViewItem sourceItem = (TreeViewItem)e.Data.GetData(typeof(TreeViewItem));
            TreeViewItem targetItem = e.Source as TreeViewItem;

            dynamic parent;

            if (targetItem == null) //not dropped in the treeview
            {
                _isDragging = false;
                return;
            }
            else if (targetItem.Parent is TreeViewItem) //drag must start from either a treeviewitem...
            {
                parent = targetItem.Parent as TreeViewItem;
            }
            else // ... or the root treeview
            {
                parent = targetItem.Parent as TreeView;
            }

            //Complete the drag/drop
            //must be same parent to successfully drop
            if(sourceItem.Parent == targetItem.Parent)
            {
                 var indexOfDropTarget = parent.Items.IndexOf(targetItem);
                 parent.Items.RemoveAt(parent.Items.IndexOf(sourceItem));
                 parent.Items.Insert(indexOfDropTarget, sourceItem);
                 sourceItem.IsSelected = true;
            }

        }

        _isDragging = false;
    }

我需要的树视图的规则是,为了重新排序而被删除的项目只能在同一个父项中重新排序。

上面的代码效果很好,假设treeviews子项都是treeview项,每个都包含我感兴趣的数据结构。

当我将新的treeview类移动到更大的项目时,我注意到因为树视图绑定到视图模型中的集合,e.Data不再是树视图项目!它现在是视图模型的数据结构。 e.Source也不再是一个树视图项目,它是整个树视图所以我无法告诉我在哪里“丢弃”该项目。

树视图是根据视图模型中的数据结构自动构建的。每个项目都有一个Children属性,Children属性中的每个项目都可以有自己的子项。我的要求是,可以对子属性中的项目进行重新排序,但不能将子项移动到其父项存储在其中的同一个集合中,也不能移动到其中一个子项集合中。

我的问题是:如何拖动TreeViewItem并删除TreeViewItem?我需要能够看到每个人的父母,并确保他们是一样的。

我是以错误的方式来做这件事的吗?我应该将命令传回视图模型吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

我认为您需要找到数据结构的容器。 如果您需要这种方式,我使用此代码完成了此操作:

TreeViewItem container = myTreeViewItem.ItemContainerGenerator.ContainerFromItem(child).As<TreeViewItem>();

你必须在树中迭代才能找到孩子的容器。因为从视图中你没有引用子对象的直接父对象的容器,你必须从root(treeview)迭代地找到它。

答案 1 :(得分:-1)

我最终做的是走在视觉树上。我能够得到事件首次出现的文本块,从那里只是走到树上直到找到合适的树视图。

我正在寻找的项目仍然存储在treeviewitem.header属性中。

如果有其他人遇到同样的问题,this link will teach you everything you need