2014-08-27 4 views
5

Я использую StackPanel для компоновки нескольких элементов управления по вертикали (т. Е. Названия, субтитров, списка, разделителя, списка и т. Д.).Повысить производительность для огромного списка в StackPanel?

StackPanel является дочерним элементом ScrollViewer, гарантируя, что его содержимое всегда прокручивается.

Одним из элементов управления в StackPanel является ListBox.

Его ItemsSource - это данные, привязанные к огромной коллекции, а сложный DataTemplate используется для реализации каждого элемента.

К сожалению, я получаю очень низкую производительность (высокий уровень/память).

Я попытался

  • установка ItemsPanel в ListBox, чтобы в VirtualizingStackPanel и
  • перекрывая его ControlTemplate только в ItemsPresenter (удалить ScrollViewer в ListBox в).

Но не было никакой разницы в характеристиках. Я предполагаю, что StackPanel дает своим внутренним детям бесконечную высоту во время измерения?

Когда я заменил ScrollViewer и StackPanel другими панелями/макетами (например, Grid, DockPanel), и производительность значительно улучшилась, что заставляет меня поверить, что узкое место, а также решение, находятся в виртуализации.

Есть ли способ улучшить производительность процессора/памяти этого вида?

enter image description here

[Update 1]

Оригинальный проект Пример: http://s000.tinyupload.com/index.php?file_id=29810707815310047536

[Update 2]

Я попытался Рестайлинг/шаблонный TreeView/TreeViewItems придумать следующий пример. Это все еще занимает много времени, чтобы начать/то же, использование высокой памяти. Но после загрузки прокрутка чувствует себя намного более отзывчивой, чем исходный образец.

Удивительно, если есть какой-либо другой способ дальнейшего улучшения времени запуска/использования памяти?Проект

рестайлинг TreeView: http://s000.tinyupload.com/index.php?file_id=00117351345725628185

[Update 2] Решение

pushpraj работает как шарм

  • Оригинал:
    • Startup: 35s,
    • памяти : 393 МБ
    • скроллинг: Slow
  • TreeView:
    • запуска: 18s,
    • 377MB памяти,
    • скроллинг: Fast
  • pushpraj в раствор:
    • Startup : < 1s,
    • Память: 20MB,
    • скроллинг: Fast

ответ

9

вы можете, возможно, ограничить максимальный размер огромного списка и включить Virtualization

например

<ListBox MaxHeight="500" 
     VirtualizingPanel.IsVirtualizing="true" 
     VirtualizingPanel.VirtualizationMode="Recycling" /> 

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

в то же самое время установка VirtualizationMode на Recycling поможет вам повторно использовать сложные шаблоны данных, тем самым устраняя необходимость повторного создания их для каждого элемента.


EDIT

здесь решение, основанное на вашем примере я использовал CompositeCollection с Virtualization для достижения желаемого.

XAML

<Grid xmlns:sys="clr-namespace:System;assembly=mscorlib" 
     xmlns:l="clr-namespace:PerfTest"> 
    <Grid.Resources> 
     <DataTemplate DataType="{x:Type l:Permission}"> 
      <StackPanel Orientation="Horizontal"> 
       <CheckBox /> 
       <TextBlock Text="{Binding Name}" /> 
       <Button Content="+" /> 
       <Button Content="-" /> 
       <Button Content="..." /> 
      </StackPanel> 
     </DataTemplate> 
     <CompositeCollection x:Key="data"> 
      <!-- Content 1 --> 
      <TextBlock Text="Title" 
         FontSize="24" 
         FontWeight="Thin" /> 
      <!-- Content 2 --> 
      <TextBlock Text="Subtitle" 
         FontSize="16" 
         FontWeight="Thin" /> 
      <!-- Content 3 --> 
      <CollectionContainer Collection="{Binding DataContext, Source={x:Reference listbox}}" /> 
      <!-- Content 4 --> 
      <TextBlock Text="User must scroll past the entire list box before seeing this" 
         FontSize="16" 
         FontWeight="Thin" 
         Padding="5" 
         TextWrapping="Wrap" 
         Background="#99000000" 
         Foreground="White" /> 
     </CompositeCollection> 
    </Grid.Resources> 
    <ListBox x:Name="listbox" 
      VirtualizingPanel.IsVirtualizing="True" 
      VirtualizingPanel.VirtualizationMode="Recycling" 
      ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
      ItemsSource="{StaticResource data}" /> 
</Grid> 

код

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     var items = new ObservableCollection<Permission>(); 
     foreach (var i in Enumerable.Range(0, 10000).Select(i => new Permission() { Name = "Permission " + i })) 
     { items.Add(i); } 
     DataContext = items; 
    } 
} 

public class Permission 
{ 
    public string Name { get; set; } 
} 

, поскольку мы не можем создать шаблон данных для строки, так что я изменил коллекцию строк в Permission коллекции. Надеюсь, в вашем реальном проекте это будет нечто похожее.

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

Примечание: вы можете спокойно игнорировать, если есть какие-либо предупреждения дизайнера на Collection="{Binding DataContext, Source={x:Reference listbox}}"

+0

Крепеж макс высоту ListBox была бы вызвать 2 скроллбары появляться (см http://i.imgur.com/s1MJ6BO.png?1) – jayars

+1

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

+0

Обновлено, чтобы включить образец проекта – jayars

Смежные вопросы