2016-07-28 32 views
0

Ich muss ListView mit verschiedenen Elementen anzeigen (insgesamt 10-15 Elementtypen). Dazu benutze ich DataTemplateSelector. Dies führt jedoch beim Crawlen zu merkwürdigem ListView-Verhalten: Irgendwann springt es an den Anfang der Listenansicht. Ich habe diesen Artikel für UWP gefunden: https://msdn.microsoft.com/en-us/windows/uwp/debug-test-perf/optimize-gridview-and-listview. Es besagt, dass ItemTemplateSelector nur 5 DataTemplates unterstütztWinRT ListView UI Virtualisierung und DataTemplateSelector mit vielen Vorlagen (10-15)

Darüber hinaus berücksichtigt ein Elementvorlage-Selektor nur fünf mögliche Kandidaten bei der Beurteilung, ob ein bestimmter Container für das aktuelle Datenelement wiederverwendet werden kann.

Ich denke, das ist der Grund. Ich habe versucht, die Anzahl der DataTemplates, die von meinem DataTemplateSelector zurückgegeben wurden, zu reduzieren, und das Problem wurde behoben: Das Scrollen funktioniert wie erwartet. Aber wie kann ich dieses Problem lösen, ohne die Anzahl der DataTemplates zu reduzieren? Ich weiß, dass ich die Virtualisierung deaktivieren kann, aber ich möchte sie nach Möglichkeit aktiviert lassen.

Für UWP gibt es eine Option für das Verwenden des ChoingItemContainer-Ereignisses, das jedoch nicht für WinRT verfügbar ist.

Ist es möglich, dieses Problem zu lösen, ohne die UI-Virtualisierung in WinRT zu deaktivieren?

+0

Benötigen Sie wirklich 10-15 verschiedene Datatemplates? Beachten Sie, dass Sie in Ihrer Datamaplle die Sichtbarkeit des Panels und der Steuerelemente einstellen können, so dass Sie beispielsweise nur ein ItemTemplate haben können, das verschiedene Informationen basierend auf dem aktuellen Datenkontext jeder Zeile anzeigt. –

+0

Ja. Es ist etwas wie Fragebogen mit verschiedenen Eingabesteuerelementen: Text, Datumsauswahl, Kontrollkästchen, Combobox, Radiobuttons, Tabellen usw. ViewModels können unterschiedliche Logik haben (z. B. die Art, wie Antworten geladen und gespeichert werden). Es ist also nicht gut, es in einem Modell zu mischen ... –

Antwort

1

Dies ist, was ich in meinem Projekt getan habe (ich habe eine Listenansicht mit unendlichem Scrollen). Grundsätzlich habe ich selbst einen Teil der Virtualisierung gemacht.

Ich entfernte DataTemplateSelector vollständig. Stattdessen verwende ich eine Vorlage für alle Elemente:

<ListView 
    ... 
    > 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <messages:MyCustomContainer /> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

Wo MyCustomContainer ein einfaches Usercontrol ist:

<UserControl 
    x:Class="MyCustomContainer" 
    ... 
    DataContextChanged="OnDataContextChanged" 
    > 
    <Grid x:Name="Container"/> 
</UserControl> 

I instanziiert und entsprechende verschachtelte Vorlage in Code auswählen hinter der MyCustomContainer:

void OnDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args) 
{ 
    var context = DataContext as MyModelThatHelpsDecideOnAppropriateVisualTemplate; 

    if (context == null) { 
     // this means, item has been removed from the list and cached (we call this 'virtualization') 
     Container.Children.Remove(CurrentTemplate); 
     ReleaseTemplate(CurrentTemplate); // clear and cache our concrete template 
     CurrentTemplate = null; 
    } else { 
     // this means, we need to get a concrete template 

     // ... some logic to decide on the proper visual template type 
     Type templateType = GetTemplateTypeForData(context); 

     // ... some logic to get visual template from cache 
     CurrentTemplate = GetTemplateFromCache(templateType); 

     Container.Children.Add(CurrentTemplate); 
    }  
} 

Auf der hellen Seite funktioniert das gut (tut für mich, und ich habe etwa ein Dutzend Artikel Vorlagen).

Auf der anderen Seite, auf diese Weise virtualisiert das UI-Framework nur MyCustomContainer Listenelemente, und Sie müssen konkrete Visualisierungen selbst zwischenspeichern. In meinem Beispiel müssen Sie Instanzen Ihrer 10-15 Vorlagen in einem Cache speichern und implementieren GetTemplateTypeForData(), GetTemplateFromCache() und ReleaseTemplate() ... Aber das sollte wirklich unkompliziert sein, nahm rund 100 Zeilen Code für mich.