Сегодня я решил, наконец, попробовать виртуализованный TreeView. Для этого требуется привязка. Поэтому я решил получить 2 теста вещей - HierarchicalDataTemplate, основанный на видах + типов.Ошибка прокрутки в Virtualized TreeView
Я создал базовый класс для некоторых данных. Создал 2 производных класса из базового класса. Сделано 2 HierarchicalDataTemplate (1 для каждого производного класса), чтобы получить различное форматирование узлов. И бегущая популяция 10 тыс. Узлов двух типов.
Классы:
public class ListItem_Generic
{
public string Name { get; protected set; }
public ListItem_Generic(string Name = "") { this.Name = Name; }
}
public class ListItem_Single : ListItem_Generic
{
public ListItem_Single(string Name = "") : base(Name) { }
}
public class ListItem_Multi : ListItem_Generic
{
public List<ListItem_Generic> Items { get; protected set; }
public ListItem_Multi(string Name = "", List<ListItem_Generic> Items = null)
: base(Name)
{
if (Items == null)
this.Items = new List<ListItem_Generic>();
else
this.Items = new List<ListItem_Generic>(Items);
}
}
Генерация 10k узлов 1-го уровня с некоторыми детьми, переплетные:
public MainWindow()
{
InitializeComponent();
// Create a list of sample items and populate them
var lst = new List<ListItem_Generic>();
int MaxHeaders = 10000;
var rnd = new Random();
// Now generate 10 000 records. First select random amount of headers
int HeadersCount = rnd.Next(MaxHeaders);
for (int i = 0; i < HeadersCount; i++)
{
var Childrencount = rnd.Next(100);
var children = new List<ListItem_Generic>();
for (int j = 0; j < Childrencount; j++)
children.Add(new ListItem_Single("Child #"+j+" of parent #"+i));
lst.Add(new ListItem_Multi("Header #" + i + " (" + Childrencount + ")", children));
}
for (int i = 0; i < MaxHeaders - HeadersCount; i++)
lst.Add(new ListItem_Single("Line #" + i));
// Bind lstView to lst
lstView.ItemsSource = lst;
lstView.UpdateLayout();
}
XAML с HierarchicalDataTemplates:
<Window x:Class="Test_DataTemplates.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:Test_DataTemplates"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TreeView Name="lstView" VirtualizingPanel.IsVirtualizing="True">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type loc:ListItem_Multi}" ItemsSource="{Binding Path=Items}">
<Border Background="RosyBrown">
<TextBlock Text="{Binding Path=Name}" Foreground="White" FontWeight="Bold"/>
</Border>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type loc:ListItem_Single}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</Window>
Все работает точно:
- TreeView получает виртуализировать (легко заметить по памяти след + время загрузки)
- узлов, полученные из типов правильно отформатирован
Тем не менее, когда прокрутка скажем заголовок # 1000 и расширяя его - положение прокрутки переместится в другое место, делая расширенный узел, а его дети НЕ видны.
Что я сделал не так? Есть ли способ исправить это?
Обновление: Удаление виртуализации также удаляет прокрутку.
связаны: http://stackoverflow.com/questions/4074475/scrolling-bug-in-wpf-virtualized- treeview –
, имеющий эту же проблему здесь – Laie
@ Jee-heonOh imho, TreeView не слишком подходит для виртуализации. Я бы посоветовал вместо этого использовать ListBox/ListView. Легко имитировать древовидный вид с помощью шаблонов и имитировать расширение уровня/сворачивание с добавлением/удалением элементов в/из простого (наблюдаемого) списка. В TreeListView имеется несколько примеров. Если вы склонны использовать TreeView (обратите внимание, что он может виртуализировать только иерархию первого уровня) - см. Обходной путь на сайте Microsoft, опубликованный одним из участников. Он переопределяет несколько событий treeviewitem, чтобы привести их в поле зрения по мере необходимости, что решает проблему прокрутки. – user2274578