更新树视图,不重复

时间:2012-12-10 20:08:31

标签: c# drag-and-drop treeview

我有两个TreeView 第一个设计如下:

A
|--B1
   |--C1
   |--C2
|--B2
   |--C3
|--B3

第二个是空的。

我实现了拖放系统,因此用户可以从我的第一个树视图拖动到第二个树视图来填充它 当一个节点被拖入TreeView时,我希望它带来他所有的父节点和子节点。 不是兄弟姐妹

示例:

如果我拖动C2,我的第二个TreeView应该是这样的

A
|--B1
   |--C2

如果我决定添加C1,它应该如下所示:

A
|--B1
   |--C1
   |--C2

我不想要像这样的副本:

 A
|--B1
   |--C2
 A
|--B1
   |--C1

所以我从这里得到两个问题(考虑到拖放已经像this那样实现了,并且只添加了没有父母或孩子的所选节点。)

  • 如何将节点带为子节点和父节点,而不是兄弟节点。它甚至可能吗?
  • 一旦第一个问题得到解答并且我有一个算法来添加一个包含所有父节点和子节点的节点,如何在不重写整个树两次的情况下更新兄弟节点?

2 个答案:

答案 0 :(得分:1)

在为一些torrent客户端编写gui时,我有同样的任务 打开torrent时,应显示包含torrent的文件和文件夹的树视图 我该如何解决呢:
我有一个文件路径列表,首先我做了什么,我已经对它进行了排序,然后使用此功能将已排序列表的项目添加到treeview

void FileTreeModel::addPath( QString path,QString size )
{
path=QDir::toNativeSeparators(path);
QStringList pathparts=path.split(QDir::separator());

FileTreeItem *iterator=rootItem,*save=rootItem;
if (rootItem->childCount()==0)
{
    //qDebug() << "root item has no childs appending current path";
    FileTreeItem* curitem=rootItem;
    for (int i=0;i<pathparts.count();i++)
    {
        curitem->appendChild(new FileTreeItem(qMakePair(pathparts.at(i),i==pathparts.count()-1? size : ""),curitem));
        curitem = curitem->child(0);
    }
    rootItem=save;
    return;
}
for (int i=0;i<pathparts.count();i++)
{
    int foundnum=-1;
    for (int j=0;j<iterator->childCount();j++)
    {
        //qDebug() << iterator->child(j)->data(0) << " " << pathparts.at(i);
        if (iterator->child(j)->data(0).toString().compare(pathparts.at(i))==0) 
        {
            //qDebug() <<"Found :" << iterator->child(j)->data(0) << " " << pathparts.at(i);
            foundnum=j;
            break;
        }
    }

    if (foundnum >= 0)
    {
        iterator = iterator->child(foundnum);
    }
    else
    {
        //qDebug() << "appending new child" << pathparts.at(i)  << " to "  << iterator->data(0) ;
        iterator->appendChild(new FileTreeItem(qMakePair(pathparts.at(i),i==pathparts.count()-1? size : ""),iterator));
        iterator = iterator->child(iterator->childCount()-1);
        //qDebug() << "new iterator value" << iterator->data(0) ;
    }

}
    rootItem=save;

}

这是Qt,但我认为你可以理解这个想法。

答案 1 :(得分:1)

更改目的地TreeViewDragDrop上的Treeview

private void treeView_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
    TreeNode NewNode;

    if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
    {
        NewNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
        if (!(sender as TreeView).Nodes.Contains(NewNode))
        {
            //Add the droped node 
            List<TreeNode> tt = new List<TreeNode>();
            TreeNode tn = (TreeNode)NewNode.Clone();
            tt.Add(tn);

            //Prepare node with it's parents until the root note
            while ((TreeNode)NewNode.Parent is TreeNode)
            {
                TreeNode tnp = (TreeNode)NewNode.Parent.Clone();

                //prevent siblings to be added
                tnp.Nodes.Clear();

                tt.Add(tnp);
                NewNode = NewNode.Parent;
            }

            //Construct the structure of the treenote to be added to the treeview
            for (int i = tt.Count - 1; i > 0; i--)
            {
                tt[i].Nodes.Add(tt[i - 1]);
            }

            /*Add the whole structured treenode to the treeview*/


            TreeNode rootnote = ExistNotes((sender as TreeView), tt[tt.Count - 1]);
            if (rootnote != null)//Root node exists, add to the existing node
            {
                foreach (TreeNode tsub in tt[tt.Count - 1].Nodes)
                {
                    AddNote(rootnote, tsub);
                }
            }
            else//Root node not exist, add to the treeview as new node.
            {
                (sender as TreeView).Nodes.Add(tt[tt.Count - 1]);
            }

            //  NewNode.Remove();
        }
    }
}

支持功能:

/// <summary>
/// Recursive function to add node
/// </summary>
/// <param name="tnbase">RootNode</param>
/// <param name="tn">Node to be added</param>
private void AddNode(TreeNode tnbase, TreeNode tn)
{
    bool exists = false;
    foreach (TreeNode rt in tnbase.Nodes)
    {
        if (this.IsNodesEquals(rt, tn))
        {
            foreach (TreeNode srt in tn.Nodes)
            {
                this.AddNode(rt, srt);
            }
            exists = true;
        }
    }
    if (!exists)
    {
        tnbase.Nodes.Add(tn);
    }
}

/// <summary>
/// Get exist node from the treeview
/// </summary>
/// <param name="tv">Treeview to check</param>
/// <param name="tn">Node to compare</param>
/// <returns></returns>
private TreeNode ExistNode(TreeView tv, TreeNode tn)
{
    TreeNode existsnote = null;
    foreach (TreeNode rt in tv.Nodes)
    {
        if (this.IsNodesEquals(rt, tn))
        {
            existsnote = rt;
        }
    }
    return existsnote;
}

/// <summary>
/// Compare two nodes by the text
/// </summary>
/// <param name="t1">node to compare</param>
/// <param name="t2">node to compare with</param>
/// <returns></returns>
private bool IsNodesEquals(TreeNode t1, TreeNode t2)
{
    return (t1 != null && t2 != null && t1.Text == t2.Text);
}