Виртуализация WPF TreeView

Я пытаюсь выяснить эту функцию виртуализации, я не уверен, что я понимаю, что это неправильно или что происходит, но я использую профилировщик памяти ANTS для проверки количества элементов в виртуализированном TreeView, и он просто продолжает расти. У меня есть TreeView с 1 ​​001 единиц (1 корень, 1000 подпозиций), и я всегда получаю до 1 001 TreeViewItems, 1,001 ToggleButtons и 1,001 TextBlocks. Разве виртуализация не должна повторно использовать элементы? Если да, то почему у меня должно быть 1 001 из них? Кроме того, CleanUpVirtualizedItem никогда не срабатывает.

Сообщите мне, если я понимаю это неправильно, и если у вас есть ресурсы, как это использовать. Я искал через Интернет, но не нашел ничего полезного.

EDIT:

Даже память, используемая деревом, растет из aporx. От 4 до 12 мб, когда я расширяю и просматриваю все элементы.

Сообщите мне спасибо.

Это мой код.

XAML:

<Window x:Class="RadTreeViewExpandedProblem.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <TreeView x:Name="treeView"
                  VirtualizingStackPanel.IsVirtualizing="True"
                  VirtualizingStackPanel.CleanUpVirtualizedItem="TreeView_CleanUpVirtualizedItem">
            <TreeView.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel />
                </ItemsPanelTemplate>
            </TreeView.ItemsPanel>
        </TreeView>
    </Grid>
</Window>

С#:

 public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            TreeViewItem rootItem = new TreeViewItem() { Header = "Item Level 0" };

            for (int i = 0; i < 1000; i++)
            {
                TreeViewItem itemLevel1 = new TreeViewItem() { Header = "Item Level 1" };

                itemLevel1.Items.Add(new TreeViewItem());

                rootItem.Items.Add(itemLevel1);
            }

            treeView.Items.Add(rootItem);
        }

        private void TreeView_CleanUpVirtualizedItem(object sender, CleanUpVirtualizedItemEventArgs e)
        {

        }
    }

Ответы

Ответ 1

Хорошо, проблема в том, что виртуализация работает только тогда, когда TreeView использует Binding, а не когда узлы генерируются один за другим в коде, как в моем примере. Какой облом.

Ответ 2

Разница заключается в виртуализации пользовательского интерфейса (который WPF поддерживает из разных элементов управления) и виртуализации данных (который WPF не поддерживает из коробки).

Это сводится к виртуализации пользовательского интерфейса только для рендеринга того, что необходимо и в пределах видимости; тогда как виртуализация данных содержит только то, что может понадобиться в данный момент времени в памяти.

У Bea есть две отличные сообщения о виртуализации пользовательского интерфейса и виртуализация данных и переходит в различия и как обходиться с ограничением поддержки виртуализации данных, которая, как представляется, является тем, что вы после.

EDIT:

Начиная с 3.5 SP1 в TreeView была добавлена ​​поддержка виртуализации. Возможно, достаточно удалить шаблон ItemsPanel и просто установить свойства в TreeView.

Ответ 3

Это не точно. Правда, что virtualuzation работает только со связыванием, однако, как я заметил в некоторых примерах приложения, переработка элементов происходит только в корневых элементах дерева.

поэтому, если у вас есть только один корневой элемент с 1000 детьми, рециркуляция не будет происходить, потому что для переработки используется только один контейнер.

если у вас есть 100 корневых элементов, и у каждого из них есть 100 детей, вы получите частичную переработку, потому что только корневые 100 элементов будут переработаны, но остальные 9900 дочерних элементов будут сохранены в памяти.

конечно, проблема становится хуже, если уровень вложенности дерева больше 2 или 3.

Я не знаю, является ли решение этой проблемы.