2014-08-27 11 views
5

Sto usando uno StackPanel per impaginare più controlli verticalmente (es. Titolo, sottotitoli, listbox, separatore, listbox, ecc.).Migliora le prestazioni per un enorme ListBox in StackPanel?

StackPanel è figlio di ScrollViewer per garantire che il suo contenuto sia sempre scorrevole.

Uno dei controlli di StackPanel è un ListBox.

L'oggetto ItemsSource è collegato a una vasta raccolta e viene utilizzato un DataTemplate complesso per la realizzazione di ciascun elemento.

Sfortunatamente, sto ottenendo prestazioni davvero scarse (alta CPU/memoria) con esso.

ho cercato

  • impostazione ItemsPanel del ListBox a un VirtualizingStackPanel, e
  • sovrascrivendo la sua ControlTemplate a solo ItemsPresenter (rimuovere ScrollViewer del ListBox).

Ma non ci sono state differenze nelle prestazioni. Immagino che StackPanel dia ai suoi figli interni un'altezza infinita durante la misurazione?

Quando ho sostituito lo ScrollViewer e StackPanel con altri pannelli/layout (per esempio, griglia, DockPanel) e la performance migliora in modo significativo, il che mi porta a credere che il collo di bottiglia, così come la soluzione, è nella virtualizzazione.

Esiste un modo per migliorare le prestazioni della cpu/memoria di questa visualizzazione?

enter image description here

[Update 1]

progetto di esempio originale: http://s000.tinyupload.com/index.php?file_id=29810707815310047536

[Aggiornamento 2]

ho cercato di restyling/template TreeView/TreeViewItems a venire con il seguente esempio. Ci vuole ancora molto tempo per iniziare/lo stesso, un elevato utilizzo della memoria. Ma una volta caricato, lo scrolling si sente molto più reattivo rispetto al campione originale.

Chiedo se c'è un altro modo per migliorare ulteriormente il tempo di avvio/l'utilizzo della memoria?progetto

Restyled TreeView: http://s000.tinyupload.com/index.php?file_id=00117351345725628185

[Update 2] soluzione

di pushpraj funziona come un fascino

  • originale:
    • avvio: 35s,
    • memoria : 393 MB
    • Scrolling:
      • avvio:: 18s,
      • memoria 377MB,
      • Scrolling: soluzione rapida
    • di pushpraj:
  • TreeView lento
    • avvio : < 1s,
    • Memoria: 20MB,
    • Scrolling: veloce

risposta

9

si può forse limitare la dimensione massima della casella di riepilogo enorme e consentire Virtualization

esempio

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

ciò consentirà al ListBox di caricare solo alcuni elementi e abiliterà una scansione llbar sulla casella di riepilogo per scorrere fino al resto degli elementi, se necessario.

allo stesso tempo l'impostazione di VirtualizationMode a Recycling consente di riutilizzare i modelli di dati complessi eliminando così la necessità di ricrearli nuovamente per ogni articolo.


EDIT

qui è una soluzione basata sul vostro campione, ho usato CompositeCollection con Virtualization per ottenere il desiderato.

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> 

codice

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

dal momento che non possiamo creare modello di dati per la stringa così ho cambiato la collezione stringa da Permission raccolta. Spero che nel tuo vero progetto sarebbe qualcosa di simile.

prova a vedere se questo è vicino a quello che ti serve.

nota: si può tranquillamente ignorare se non v'è alcun avvertimento designer su Collection="{Binding DataContext, Source={x:Reference listbox}}"

+0

fissaggio altezza massima della casella di riepilogo causerebbe 2 barre di scorrimento ad apparire (vedi http://i.imgur.com/s1MJ6BO.png?1) – jayars

+1

questo è vero, ma allo stesso tempo la virtualizzazione può funzionare solo quando l'altezza è fissa o l'altezza massima è definita, non può funzionare per un'altezza illimitata. Potresti forse utilizzare la raccolta composita combinare tutti gli elementi nello stackpanel e visualizzarli tutti in una listbox con la virtualizzazione abilitata. potresti condividere il codice, cercherò di aiutarti con quello. – pushpraj

+0

Aggiornato per includere il progetto di esempio – jayars

Problemi correlati