Очистить вид дерева Silverlight с иерархией - PullRequest
0 голосов
/ 15 февраля 2012

У меня есть древовидное представление В приложении SL 4, которое я создаю динамически с помощью метода WCF.Древовидное представление состоит из папок и документов.Мне нужно иметь возможность перестраивать дерево при добавлении пакетов документов.

Как очистить все элементы из представления дерева SL ?, и не говорите TreeView.Items.Clear(), потому что это не работает.Также невозможно использовать цикл foreach для удаления всех элементов и их дочерних элементов.Я говорю статью здесь , но нигде не вижу TreeView.Children.Copy или TreeView.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

Вид дерева, очевидно, заполняется, когдастраница загружается, и метод NewDocumentTree_Received вызывается при публикации и обновлении WCF.

ОШИБКА в экземпляре: «Элементы с одинаковым ключом уже добавлены» *

Что говорит мне одерево не очищается и не обновляется, иначе дерево не заполнилось бы в первую очередь ... надеюсь, помощь прояснит ситуацию.

Ответы [ 3 ]

0 голосов
/ 16 февраля 2012

Я не мог воспроизвести любую проблему с TreeView.Items.Clear(). Ниже приведен код, который я добавил в новый проект приложения Silverlight в Visual Web Developer Express:

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));
    }

Одна вещь, которой вы не поделились, - это XAML, который вы используете для отображения TreeView. Вы случайно не связали ItemsSource дерева в вашей XAML с чем-то, не так ли? (Я говорю это потому, что вы упоминаете, что вызов ClearValue на ItemsSourceProperty, кажется, исправит ваши проблемы, и это наводит меня на мысль, что для этого свойства есть привязка. Однако я понимаю, что остальная часть вашего кода собирает дерево в коде позади, присваивая свойству Items.)


Между прочим, следующий цикл (в RemoveTreeViewSubItems) не будет работать, если tvi.Items уже пуст:

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

Вы не можете удалять элементы из коллекции, поскольку выполняете итерации по ней. Если вы попытаетесь это сделать, вы получите сообщение об ошибке «Операция недействительна из-за текущего состояния объекта».

0 голосов
/ 28 февраля 2013

У меня была похожая проблема, 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, а унаследовал от него объект.

0 голосов
/ 15 февраля 2012

Я изменил способ создания TreeView, поэтому я использую TreeView.ItemsSource и назначаю для него список TreeViewItems.Затем я использую метод TreeView.ClearValue (TreeView.ItemsSourceProperty), чтобы очистить дерево, а затем снова заполнить его новым источником элементов ... который, похоже, выполняет свою работу.

Me.docTreeView.ClearValue(TreeView.ItemsSourceProperty)

Me.docTreeView = New TreeView

Me.docTreeView.ItemsSource = Nothing

PopulateDocTreeView()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...