清除带有层次结构的silverlight树视图

时间:2012-02-14 20:19:46

标签: silverlight treeview

我有一个树视图在我通过WCF方法动态构建的SL 4应用程序中。树视图由文件夹和文档组成。我需要能够在添加批量文档时重建树。

如何清除SL树视图中的所有项目?并且不要说TreeView.Items.Clear()因为这不起作用。也不可能使用foreach循环删除所有项目及其子项。我说了一篇文章here,但在任何地方都看不到TreeView.Children.CopyTreeView.Items.Copy。这是我尝试过的最后一件事,我感到茫然...

如果你知道如何完成这件事,请告诉我。谢谢!

Private Sub NewDocumentTree_Received(ByVal sender As Object, ByVal e As GetDocumentTreeCompletedEventArgs)
        Me.ThisDocTreeView = e.Result
        ClearTree()
        PopulateDocTreeView()
    End Sub

    Private Sub ClearTree()
        Dim tempTree As New TreeView()
        tempTree = CopyTreeViewToNewObject(Me.docTreeView)
        For Each tvi As TreeViewItem In tempTree.Items
            For Each sub_tvi As TreeViewItem In tvi.Items
                For Each d_tvi As TreeViewItem In sub_tvi.Items
                    RemoveTreeViewSubItems(d_tvi)
                Next
                RemoveTreeViewSubItems(sub_tvi)
            Next
            RemoveTreeViewSubItems(tvi)
        Next
        tempTree.UpdateLayout()

        Me.docTreeView = tempTree
        Me.docTreeView.UpdateLayout()
    End Sub

    Private Sub RemoveTreeViewSubItems(ByVal tvi As TreeViewItem)
        For Each sub_tvi As TreeViewItem In tvi.Items
            tvi.Items.Remove(sub_tvi)
            tvi.UpdateLayout()
        Next
    End Sub

    Private Function CopyTreeViewToNewObject(ByVal treeview As TreeView) As TreeView
        Dim newTree As New TreeView()
        For Each Parent As TreeViewItem In treeview.Items
            newTree.Items.Add(GetTreeViewItemAndChildren(Parent))
        Next
        Return newTree
    End Function

    Private Function GetTreeViewItemAndChildren(ByVal treeViewItem As TreeViewItem)
        Dim ParentalItem As New TreeViewItem
        ParentalItem = treeViewItem
        For Each child As TreeViewItem In treeViewItem.Items
            Dim firstChild As New TreeViewItem
            firstChild = child
            For Each subChild As TreeViewItem In child.Items
                Dim secondChild As New TreeViewItem
                secondChild = child
                firstChild.Items.Add(secondChild)
            Next
            ParentalItem.Items.Add(firstChild)
        Next

        Return ParentalItem
    End Function

更新:以下是从我的WCF服务接收对树的批量更新的通知以及构建树视图的主要方法的方法。

    Private Sub NewDocumentTree_Received(ByVal sender As Object, ByVal e As GetDocumentTreeCompletedEventArgs)

        Me.ThisDocTreeView = e.Result

        Me.docTreeView.Items.Clear()

        Me.docTreeView.UpdateLayout()

        PopulateDocTreeView()

    End Sub

Private Sub PopulateDocTreeView()

        'ensure all items are clear
        Me.docTreeView.Items.Clear()

        'loop through root folder to extract parent "user" folders, and examine sub folders
        For Each folder As PortalOnline.PortalDocRootFolder In ThisDocTreeView.RootFolders

            'get this users folder as a tree view items
            Dim parent As TreeViewItem = GetParentTreeViewFolder(folder)

            'define a new list of category folders based on this users documents
            Dim catFolders As List(Of TreeViewItem) = GetCategoryFolderList(folder)

            'loop through the subfolders of the users parent folder for document and get each document folder
            'as a new tree view item
            For Each child As PortalOnline.PortalDocInfo In folder.SubFolders

                'define the document tree view item
                Dim childItem As TreeViewItem = GetDocumentTreeItem(child, folder)

                'loop through the category folders, and add the document tree view item to the appropriate folder
                For Each categoryfolder As TreeViewItem In catFolders

                    Dim childMeta As DocTreeViewItem = childItem.Tag

                    'if the category tree veiw item head matches the document category of the document tree view item
                    'then add the document tree view item into that category folder
                    If categoryfolder.Header = childMeta.DocumentCategory Then

                        categoryfolder.Items.Add(childItem)

                    End If

                Next

            Next

            'add all category folders to the users parent folder
            For Each subfolder As TreeViewItem In catFolders

                parent.Items.Add(subfolder)

            Next

            'add the users parent folder to the tree view
            docTreeView.Items.Add(parent)

        Next

    End Sub

当页面加载时,树视图显然正在填充,并且在WCF发布和更新时调用NewDocumentTree_Received方法。

实例中的错误: "已添加具有相同键的项目"

这告诉我树没有被清除和更新,否则树不会首先填充...希望帮助澄清情况。

3 个答案:

答案 0 :(得分:0)

我改变了构建TreeView的方式,因此我使用TreeView.ItemsSource并为其分配TreeViewItems列表。然后我使用TreeView.ClearValue(TreeView.ItemsSourceProperty)方法清除树,然后使用新项源重新填充它..这似乎可以完成工作。

Me.docTreeView.ClearValue(TreeView.ItemsSourceProperty)

Me.docTreeView = New TreeView

Me.docTreeView.ItemsSource = Nothing

PopulateDocTreeView()

答案 1 :(得分:0)

我无法使用TreeView.Items.Clear()重现任何问题。下面是我在Visual Web Developer Express中添加到新Silverlight应用程序项目的代码:

MainPage.xaml(根<UserControl>元素的内容):

<StackPanel>
    <Button Content="1" Click="Button1_Click" />
    <Button Content="2" Click="Button2_Click" />
    <sdk:TreeView x:Name="docTreeView" />
</StackPanel>

MainPage.xaml.cs(MainPage()构造函数下方):

    private void Button1_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        List<TreeViewItem> items3 = new List<TreeViewItem>() { new TreeViewItem() { Header = "1.b.i" }, new TreeViewItem() { Header = "1.b.ii" }, new TreeViewItem() { Header = "1.b.iii" } };
        List<TreeViewItem> items2 = new List<TreeViewItem>() { new TreeViewItem() { Header = "1.a" }, new TreeViewItem() { Header = "1.b" }, new TreeViewItem() { Header = "1.c" } };
        items3.ForEach(item => items2[1].Items.Add(item));
        List<TreeViewItem> items1 = new List<TreeViewItem>() { new TreeViewItem() { Header = "1" }, new TreeViewItem() { Header = "2" }, new TreeViewItem() { Header = "3" } };
        items2.ForEach(item => items1[0].Items.Add(item));

        docTreeView.Items.Clear();
        items1.ForEach(item => docTreeView.Items.Add(item));
    }

    private void Button2_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        List<TreeViewItem> items3 = new List<TreeViewItem>() { new TreeViewItem() { Header = "TWO.B.I" }, new TreeViewItem() { Header = "TWO.B.II" }, new TreeViewItem() { Header = "TWO.B.III" } };
        List<TreeViewItem> items2 = new List<TreeViewItem>() { new TreeViewItem() { Header = "TWO.A" }, new TreeViewItem() { Header = "TWO.B" }, new TreeViewItem() { Header = "TWO.C" } };
        items3.ForEach(item => items2[1].Items.Add(item));
        List<TreeViewItem> items1 = new List<TreeViewItem>() { new TreeViewItem() { Header = "ONE" }, new TreeViewItem() { Header = "TWO" }, new TreeViewItem() { Header = "THREE" } };
        items2.ForEach(item => items1[1].Items.Add(item));

        docTreeView.Items.Clear();
        items1.ForEach(item => docTreeView.Items.Add(item));
    }

您尚未分享的一件事是您用来显示TreeView的XAML。你没有任何机会,将你的XAML中的ItemsSource树视图绑定到某个东西,对吗? (我这样说是因为你提到在ClearValue上调用ItemsSourceProperty似乎可以为你解决问题,这表明我对该属性有约束力。但是,我的理解是其余的您的代码通过分配给Items属性来组装代码隐藏中的树。)


顺便提一下,以下循环(在RemoveTreeViewSubItems中)不起作用,除非tvi.Items已经为空:

    For Each sub_tvi As TreeViewItem In tvi.Items
        tvi.Items.Remove(sub_tvi)
        tvi.UpdateLayout()
    Next

在迭代集合时,无法从集合中删除项目。如果您尝试这样做,您将得到“由于对象的当前状态而导致操作无效”错误。

答案 2 :(得分:0)

我有类似的问题,Items.Clear()会挂起我的应用程序。我用下面的代码修复了它。它会从孩子开始删除每个项目并逐步完成。

    private void ClearFix()
    {
            RemoveKids(this.Items);
    }

    private void RemoveKids(ItemCollection ItemsColl)
    {
        foreach (object obj in ItemsColl.ToArray())
        {
            TreeViewItem tvi = obj as TreeViewItem;

            if (tvi == null)
                continue;

            if (tvi.HasItems)
                RemoveKids(tvi.Items);

            this.Items.Remove(tvi);
        }
    }

注意我必须使用ItemColl.ToArray(),因为如果更改正在迭代的集合,将会出现错误。

不确定这是否会增加问题,但我实际上并没有使用TreeViewItem,而是继承了它的对象。