WP7: Когда в ListBox используется VirtualizingStackPanel?

#silverlight #windows-phone-7 #virtualizingstackpanel

#silverlight #windows-phone-7 #virtualizingstackpanel

Вопрос:

Все говорят, что по умолчанию ItemsPanel для ListBox является VirtualizingStackPanel. Я создал класс, производный от ListBox (назовем его MyListBox), и вместо этого по умолчанию используется StackPanel.

Я имею в виду, что я должен принудительно выполнить виртуализацию, например, таким образом:

 const string itemsPanelTemplateString = @"
<ItemsPanelTemplate
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
<VirtualizingStackPanel/>
</ItemsPanelTemplate>";

MyListBox {
    this.ItemsPanel = (ItemsPanelTemplate)
        System.Windows.Markup.XamlReader.Load(itemsPanelTemplateString);
}
  

Я мог бы перепечатать здесь свой класс, но дело не в этом. Я хотел бы знать общий ответ.

Класс не изменяет предопределенного стиля ListBox, но использует собственный класс, производный от ListBoxItem.

Я почти уверен, что существуют некоторые условия для использования виртуализации, поскольку мой коллега сказал, что видел соответствующий код ListBox в прошлом. К сожалению, прямо сейчас у нас нет доступа к отладочным версиям MS dll.

Комментарии:

1. Вы могли бы просто изменить ItemsPanel ListBox с помощью XAML.

2. Конечно. Представленный мной код делает то же самое, хотя и в коде. Но мой вопрос в другом — почему виртуализация не была применена. Я не хочу изучать визуальное дерево каждый раз, когда использую ListBox 🙂

3. Можете ли вы продемонстрировать, как вы определяете, что используется StackPanel ?

4. Два способа: а) Подсчет количества элементов, которые были созданы. (Для большого набора данных, конечно.) б) Удаление визуального дерева. Перечислены имена классов.

5. Хороший класс для сброса визуального дерева можно найти по адресу dl.dropbox.com/u/254416/blog/TreeHelper.cs

Ответ №1:

ListBox и элементы управления, производные от ListBox, по умолчанию будут иметь VirtualizedStackPanel в качестве ItemsPanel, если пользовательский код не изменит это явно.

Однако, если ваш пользовательский ListBox является производным непосредственно от ItemsControl (как указано в фактическом выводе из ListBox), тогда вы получите StackPanel в качестве ItemsPanel по умолчанию.

Может ли это быть в вашем коде? Если нет, пожалуйста, поделитесь своим управляющим кодом.

Комментарии:

1. MyListBox является производным от ListBox, MyListBoxItem — производным от ListBoxItem. Я знаю, что вы цитировали документацию msdn, но это утверждение просто не соответствует действительности. а) Мой пример доказывает это. б) Код ListBox, показанный .Net Reflector, также должен это подтверждать.

Ответ №2:

Решена. Это была моя ошибка:

При переопределении ListBox.При использовании функции appplytemplate() (с целью измерения времени) я забыл вызвать base.OnApplyTemplate(). По-видимому, выбор панели элементов выполняется там.

Опасная ошибка, потому что, казалось бы, все работало.

Спасибо всем, кто пытался помочь.

Ответ №3:

Стиль по умолчанию для ListBox не присваивает шаблон ItemsPanel.

Согласно внутреннему коду, который я вижу в reflector, он OnApplyTemplate назначит VirtualizingStackPanel внутреннему, ItemsHost если ItemsPanel шаблон не предоставлен.

Возможно, включение кода вашего класса в конце концов может оказаться хорошей идеей.

Комментарии:

1. ItemsPanel не была предоставлена. (Прямо сейчас для него установлено значение VirtualizingStackPanel для принудительного выполнения ожидаемого поведения.) Я бы включил код класса, но в нем 900 строк. И в два раза больше, если я включу код, использующий этот класс. Неважно, я попытаюсь исследовать это дальше и сообщу о результате.

Ответ №4:

Вы можете найти хорошие рекомендации по повышению производительности Listbox на http://blogs.msdn.com/b/slmperf/archive/2010/10/06/silverlight-for-windows-phone-7-listbox-scroll-performance.aspx

Также есть хорошая альтернатива, описанная на http://blogs.msdn.com/b/delay/archive/2010/09/08/never-do-today-what-you-can-put-off-till-tomorrow-deferredloadlistbox-and-stackpanel-help-windows-phone-7-lists-scroll-smoothly-and-consistently.aspx

Еще одна вещь, на которую следует обратить внимание (по-видимому), заключается в том, что вы также получите виртуализацию, только если коллекция, к которой вы привязываетесь, реализует IList .

Комментарии:

1. Последнее предложение не совсем точное. Если вы привязываете что-либо меньшее, чем IList (ICollection или IEnumerable), то ItemsControl просто впитает всю коллекцию в свою собственную внутреннюю реализацию IList . Оттуда вы все равно получите преимущества виртуализации элементов пользовательского интерфейса. Однако кто-то, использующий, скажем, a, IEnumerable<x> предоставляемый функцией utalizing yield return , может быть удивлен тем, что все элементы, сгенерированные функцией, полностью используются с самого начала.

2. В этом конкретном примере MyListBox привязывается к ObservableCollection<Customer>.