Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Opmerking Zie de sessie //build/ Aanzienlijk verbeteren van de prestaties wanneer gebruikers werken met grote hoeveelheden gegevens in GridView en ListView voor meer informatie.
Verbeter de prestaties en opstarttijd van ListView en GridView via ui-virtualisatie, elementreductie en progressief bijwerken van items. Zie ListView- en GridView-gegevensvirtualisatie voor WinUI voor gegevensvirtualisatietechnieken.
Twee belangrijke factoren in de prestaties van verzamelingen
Het bewerken van verzamelingen is een veelvoorkomend scenario. Een fotoviewer heeft verzamelingen foto's, een lezer heeft verzamelingen artikelen, boeken of verhalen en een winkel-app bevat verzamelingen producten. In dit onderwerp wordt beschreven wat u kunt doen om uw WinUI-app efficiënt te maken bij het bewerken van verzamelingen.
Er zijn twee belangrijke factoren in prestaties als het gaat om verzamelingen: een is de tijd die wordt besteed door de ui-thread die items maakt; de andere is het geheugen dat wordt gebruikt door zowel de onbewerkte gegevensset als de ui-elementen die worden gebruikt om die gegevens weer te geven.
Voor vloeiend pannen en schuiven is het essentieel dat de UI-thread een efficiënte en slimme taak uitvoert voor het instantiëren, verbinden van gegevens en het opmaken van items.
UI-virtualisatie
UI-virtualisatie is de belangrijkste verbetering die u kunt aanbrengen. Dit betekent dat UI-elementen die de items vertegenwoordigen, op aanvraag worden gemaakt. Voor een itembesturingselement dat is gebonden aan een verzameling van 1000 items, is het een verspilling van resources om de gebruikersinterface voor alle items tegelijk te maken, omdat ze niet allemaal tegelijkertijd kunnen worden weergegeven. ListView en GridView (en andere standaardbesturingselementen van ItemsControl) voeren ui-virtualisatie voor u uit. Wanneer items bijna in beeld worden geschoven (een paar pagina's weg), genereert het framework de gebruikersinterface voor de items en slaat deze in de cache op. Als het onwaarschijnlijk is dat de items opnieuw worden weergegeven, maakt het framework het geheugen vrij.
Als u een aangepaste items-paneel sjabloon opgeeft (zie ItemsPanel), moet u een virtualiserend paneel gebruiken, zoals ItemsWrapGrid of ItemsStackPanel. Als u VariableSizedWrapGrid, WrapGrid of StackPanel gebruikt, krijgt u geen virtualisatie. Daarnaast worden de volgende ListView-gebeurtenissen alleen gegenereerd wanneer u een ItemsWrapGrid of een ItemsStackPanel gebruikt: ChoosingGroupHeaderContainer, ChoosingItemContainer en ContainerContentChanging. Voor aangepaste indelingen in Windows App SDK is het moderne equivalent een implementatie op basis van VirtualizingLayout wanneer de ingebouwde itemspanels niet aan uw behoeften voldoen.
Het concept van een viewport is essentieel voor UI-virtualisatie, omdat het framework de elementen moet maken die waarschijnlijk worden weergegeven. Over het algemeen is de viewport van een ItemsControl het bereik van het logische controle-element. De viewport van een ListView is bijvoorbeeld de breedte en hoogte van het Element ListView . Sommige panelen bieden onbeperkte ruimte voor onderliggende elementen, zoals ScrollViewer en een raster met rijen of kolommen met automatisch formaat. Wanneer een gevirtualiseerde ItemsControl in een paneel als dat wordt geplaatst, is er voldoende ruimte nodig om alle items weer te geven, waardoor virtualisatie wordt verslagen. Herstel virtualisatie door een breedte en hoogte in te stellen op ItemsControl.
Reductie van elementen per item
Houd het aantal UI-elementen dat wordt gebruikt om uw items tot een redelijk minimum weer te geven.
Wanneer een itembeheer voor het eerst wordt weergegeven, worden alle elementen gemaakt die nodig zijn om een viewport vol items weer te geven. Als items de viewport naderen, werkt het framework ook de UI-elementen bij in de sjablonen voor items in de cache met de afhankelijke gegevensobjecten. Het minimaliseren van de complexiteit van de markeringen in sjablonen betaalt af in het geheugen en in de tijd die is besteed aan de UI-thread, waardoor de reactiesnelheid wordt verbeterd, met name tijdens het pannen en schuiven. De betreffende sjablonen zijn de itemsjabloon (zie ItemTemplate) en de bedieningssjabloon van een ListViewItem of een GridViewItem (het itembesturingssjabloon of ItemContainerStyle). Het voordeel van zelfs een kleine vermindering van het aantal elementen wordt vermenigvuldigd met het aantal weergegeven items.
Zie XAML-laden optimaliseren voor WinUI en Windows App SDK voor voorbeelden van het verminderen van elementen.
De standaardbesturingselementsjablonen voor ListViewItem en GridViewItem bevatten een ListViewItemPresenter-element . Deze presentator is één enkel geoptimaliseerd element dat complexe visuele elementen weergeeft voor focus, selectie en andere visuele toestanden. Als u al aangepaste sjablonen voor itembeheer (ItemContainerStyle) hebt of als u in de toekomst een kopie van een itembesturingselementsjabloon bewerkt, raden we u aan een ListViewItemPresenter te gebruiken omdat dit element u in de meeste gevallen een optimale balans biedt tussen prestaties en aanpasbaarheid. U kunt de presentator aanpassen door er eigenschappen op in te stellen. Hier ziet u bijvoorbeeld markeringen waarmee het vinkje wordt verwijderd dat standaard wordt weergegeven wanneer een item is geselecteerd en de achtergrondkleur van het geselecteerde item wordt gewijzigd in oranje.
...
<ListView>
...
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter SelectionCheckMarkVisualEnabled="False" SelectedBackground="Orange"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
<!-- ... -->
Er zijn ongeveer 25 eigenschappen met zelfbeschrijfbare namen die vergelijkbaar zijn met SelectionCheckMarkVisualEnabled en SelectedBackground. Als de presentatortypen niet aanpasbaar genoeg blijken te zijn voor uw use-case, kunt u in plaats daarvan een kopie van de ListViewItemExpanded-sjabloon of het GridViewItemExpanded-besturingselement sjabloon bewerken. Bekijk in een WinUI-app het generic.xaml bestand dat wordt geleverd met het Windows App SDK-pakket voor de huidige standaardsjablonen. Houd er rekening mee dat het gebruik van deze sjablonen betekent dat je wat prestaties inruilt voor meer aanpassingsmogelijkheden.
ListView- en GridView-items geleidelijk bijwerken
Als u gegevensvirtualisatie gebruikt, kunt u de reactiesnelheid van ListView en GridView hoog houden door het besturingselement zo te configureren dat tijdelijke UI-elementen worden weergegeven voor de items die nog worden gedownload. De tijdelijke elementen worden vervolgens geleidelijk vervangen door de werkelijke gebruikersinterface wanneer gegevens worden geladen.
Ongeacht waar u gegevens laadt (lokale schijf, netwerk of cloud), kan een gebruiker een ListView of GridView zo snel pannen of schuiven dat het niet mogelijk is om elk item met volledige betrouwbaarheid weer te geven terwijl het soepel pannen en schuiven behouden blijft. Om soepel pannen en scrollen te behouden, kunt u ervoor kiezen om een item in meerdere fasen weer te geven, naast het gebruik van tijdelijke aanduidingen.
Een voorbeeld van deze technieken wordt vaak gezien in apps voor het weergeven van foto's, ook al zijn niet alle afbeeldingen geladen en weergegeven, kan de gebruiker nog steeds pannen, schuiven en werken met de verzameling. Of voor een filmitem kunt u de titel in de eerste fase, de beoordeling in de tweede fase en een afbeelding van de poster in de derde fase weergeven. De gebruiker ziet de belangrijkste gegevens over elk item zo vroeg mogelijk en dat betekent dat ze in één keer actie kunnen ondernemen. Vervolgens wordt de minder belangrijke informatie ingevuld naarmate tijd het toelaat. Hier volgen de platformfuncties die u kunt gebruiken om deze technieken te implementeren.
Plaatsaanduidingen
De functie voor plaatsaanduidingsafbeeldingen is standaard ingeschakeld en wordt beheerd met de eigenschap ShowsScrollingPlaceholders. Tijdens het snel pannen en scrollen geeft deze functie de gebruiker een visuele hint dat er nog meer items zijn die nog volledig moeten worden weergegeven, terwijl de vloeiendheid behouden blijft. Als u een van de onderstaande technieken gebruikt, kunt u ShowsScrollingPlaceholders instellen op false als u liever geen plaatsaanduidingen wilt renderen.
Updates van progressieve gegevenssjablonen met behulp van x:Phase
Het x:Phase kenmerk blijft werken in WinUI en blijft een goede manier om iteminhoud geleidelijk weer te geven.
U kunt als volgt het kenmerk x:Phase gebruiken met {x:Bind} -bindingen om progressieve gegevenssjabloonupdates te implementeren.
Hier ziet de bindingsbron eruit (dit is de gegevensbron waarmee we verbinding maken).
namespace LotsOfItems { public class ExampleItem { public string Title { get; set; } public string Subtitle { get; set; } public string Description { get; set; } } public class ExampleItemViewModel { private ObservableCollection<ExampleItem> exampleItems = new ObservableCollection<ExampleItem>(); public ObservableCollection<ExampleItem> ExampleItems { get { return this.exampleItems; } } public ExampleItemViewModel() { for (int i = 1; i < 150000; i++) { this.exampleItems.Add(new ExampleItem(){ Title = "Title: " + i.ToString(), Subtitle = "Sub: " + i.ToString(), Description = "Desc: " + i.ToString() }); } } } }Hier is de markering die
DeferMainPage.xamlbevat. De rasterweergave bevat een itemsjabloon met elementen die zijn gebonden aan de eigenschappen Titel, Subtitel en Beschrijving van de klasse MyItem . Houd er rekening mee dat x:Phase standaard 0 is. Hier worden items in eerste instantie weergegeven met alleen de titel die zichtbaar is. Vervolgens is het ondertitelingselement gegevens gebonden en zichtbaar gemaakt voor alle items, enzovoort totdat alle fasen zijn verwerkt.<Page x:Class="LotsOfItems.DeferMainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:lotsOfItems="using:LotsOfItems" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <GridView ItemsSource="{x:Bind ViewModel.ExampleItems}"> <GridView.ItemTemplate> <DataTemplate x:DataType="lotsOfItems:ExampleItem"> <StackPanel Height="100" Width="100" Background="OrangeRed"> <TextBlock Text="{x:Bind Title}"/> <TextBlock Text="{x:Bind Subtitle}" x:Phase="1"/> <TextBlock Text="{x:Bind Description}" x:Phase="2"/> </StackPanel> </DataTemplate> </GridView.ItemTemplate> </GridView> </Grid> </Page>Als u de app nu uitvoert en snel door de rasterweergave schuift of schuift, ziet u dat wanneer elk nieuw item op het scherm wordt weergegeven, het eerst wordt weergegeven als een donkergrijze rechthoek (dankzij de eigenschap ShowsScrollingPlaceholders standaard ingesteld op true), wordt de titel weergegeven, gevolgd door ondertitel, gevolgd door beschrijving.
Updates van progressieve gegevenssjablonen met ContainerContentChanging
De algemene strategie voor de Gebeurtenis ContainerContentChanging is om Opacity te gebruiken om elementen te verbergen die niet direct zichtbaar hoeven te zijn. Wanneer elementen worden gerecycled, behouden ze hun oude waarden, dus willen we deze elementen verbergen totdat we deze waarden uit het nieuwe gegevensitem hebben bijgewerkt. We gebruiken de eigenschap Fase op de gebeurtenisargumenten om te bepalen welke elementen moeten worden bijgewerkt en weergegeven. Als er extra fasen nodig zijn, registreren we een callback.
We gebruiken dezelfde bindingsbron als voor x:Phase.
Hier is de markup die
MainPage.xamlbevat. De rasterweergave declareert een handler voor de gebeurtenis ContainerContentChanging en bevat een itemsjabloon met elementen die worden gebruikt om de eigenschappen Titel, Subtitel en Beschrijving van de klasse MyItem weer te geven. Om de maximale prestatievoordelen van het gebruik van ContainerContentChanging te verkrijgen, gebruiken we geen bindingen in de markering en wijzen we in plaats daarvan programmatisch waarden toe. De uitzondering hier is het element dat de titel weergeeft, die we in fase 0 beschouwen.<Page x:Class="LotsOfItems.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:lotsOfItems="using:LotsOfItems" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <GridView ItemsSource="{x:Bind ViewModel.ExampleItems}" ContainerContentChanging="GridView_ContainerContentChanging"> <GridView.ItemTemplate> <DataTemplate x:DataType="lotsOfItems:ExampleItem"> <StackPanel Height="100" Width="100" Background="OrangeRed"> <TextBlock Text="{x:Bind Title}"/> <TextBlock Opacity="0"/> <TextBlock Opacity="0"/> </StackPanel> </DataTemplate> </GridView.ItemTemplate> </GridView> </Grid> </Page>Ten slotte is hier de implementatie van de ContainerContentChanging-gebeurtenis-handler . Deze code laat ook zien hoe we een eigenschap van het type ExampleItemViewModel toevoegen aan MainPage om de bindingbronklasse weer te geven uit de klasse die onze pagina met markeringen vertegenwoordigt. Zolang u geen {Binding}- bindingen in uw gegevenssjabloon hebt, markeert u het object gebeurtenisargumenten zoals verwerkt in de eerste fase van de handler om aan te geven dat het item geen gegevenscontext hoeft in te stellen.
namespace LotsOfItems { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); this.ViewModel = new ExampleItemViewModel(); } public ExampleItemViewModel ViewModel { get; set; } // Display each item incrementally to improve performance. private void GridView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { if (args.Phase != 0) { throw new System.Exception("We should be in phase 0, but we are not."); } // It's phase 0, so this item's title will already be bound and displayed. args.RegisterUpdateCallback(this.ShowSubtitle); args.Handled = true; } private void ShowSubtitle(ListViewBase sender, ContainerContentChangingEventArgs args) { if (args.Phase != 1) { throw new System.Exception("We should be in phase 1, but we are not."); } // It's phase 1, so show this item's subtitle. var templateRoot = args.ItemContainer.ContentTemplateRoot as StackPanel; var textBlock = templateRoot.Children[1] as TextBlock; textBlock.Text = (args.Item as ExampleItem).Subtitle; textBlock.Opacity = 1; args.RegisterUpdateCallback(this.ShowDescription); } private void ShowDescription(ListViewBase sender, ContainerContentChangingEventArgs args) { if (args.Phase != 2) { throw new System.Exception("We should be in phase 2, but we are not."); } // It's phase 2, so show this item's description. var templateRoot = args.ItemContainer.ContentTemplateRoot as StackPanel; var textBlock = templateRoot.Children[2] as TextBlock; textBlock.Text = (args.Item as ExampleItem).Description; textBlock.Opacity = 1; } } }Als u de app nu uitvoert en snel door de rasterweergave bladert of scrolt, ziet u hetzelfde gedrag als voor x:Phase.
Containerrecycling met heterogene verzamelingen
In sommige toepassingen moet u een andere gebruikersinterface hebben voor verschillende typen items in een verzameling. Dit kan een situatie creëren waarin het voor virtualiserende deelvensters onmogelijk is om de visuele elementen die gebruikt worden voor het weergeven van de items, opnieuw te gebruiken of te recyclen. Als u de visuele elementen voor een item opnieuw wilt maken tijdens pannen, worden veel van de prestatiewinsten die worden geboden door virtualisatie ongedaan gemaakt. Met een beetje planning kun je de panelen virtualiseren om de elementen opnieuw te gebruiken. Ontwikkelaars hebben een aantal opties, afhankelijk van hun scenario: de gebeurtenis ChoosingItemContainer of een itemsjabloonkiezer. De benadering ChoosingItemContainer heeft betere prestaties.
De gebeurtenis ChoosingItemContainer
Het kiezen vanItemContainer is een gebeurtenis waarmee u een item (ListViewItem of GridViewItem) aan de ListView of GridView kunt opgeven wanneer een nieuw item nodig is tijdens het opstarten of recyclen. U kunt een container maken op basis van het type gegevensitem dat door de container wordt weergegeven, zoals wordt weergegeven in het onderstaande voorbeeld. Het kiezen vanItemContainer is de betere manier om verschillende gegevenssjablonen voor verschillende items te gebruiken. Containercaching is iets dat kan worden bereikt door gebruik te maken van ChoosingItemContainer. Als u bijvoorbeeld vijf verschillende sjablonen hebt, waarbij één sjabloon vaker een groottevolgorde heeft dan de andere, kunt u met ChoosingItemContainer niet alleen items maken op basis van de benodigde verhoudingen, maar ook een geschikt aantal elementen in de cache opslaan en beschikbaar houden voor recycling. Het kiezen vanGroupHeaderContainer biedt dezelfde functionaliteit voor groepsheaders.
// Example shows how to use ChoosingItemContainer to return the correct
// DataTemplate when one is available. This example shows how to return different
// data templates based on the type of FileItem. Available ListViewItems are kept
// in two separate lists based on the type of DataTemplate needed.
private void ListView_ChoosingItemContainer
(ListViewBase sender, ChoosingItemContainerEventArgs args)
{
// Determines type of FileItem from the item passed in.
bool special = args.Item is DifferentFileItem;
// Uses the Tag property to keep track of whether a particular ListViewItem's
// datatemplate should be a simple or a special one.
string tag = special ? "specialFiles" : "simpleFiles";
// Based on the type of datatemplate needed return the correct list of
// ListViewItems, this could have also been handled with a hash table. These
// two lists are being used to keep track of ItemContainers that can be reused.
List<UIElement> relevantStorage = special ? specialFileItemTrees : simpleFileItemTrees;
// args.ItemContainer is used to indicate whether the ListView is proposing an
// ItemContainer (ListViewItem) to use. If args.ItemContainer is not null, then
// there was a recycled ItemContainer available to be reused.
if (args.ItemContainer != null)
{
// The Tag is being used to determine whether this is a special file or
// a simple file.
if (args.ItemContainer.Tag.Equals(tag))
{
// Great: the system suggested a container that is actually going to
// work well.
}
else
{
// The ItemContainer's datatemplate does not match the needed
// datatemplate.
args.ItemContainer = null;
}
}
if (args.ItemContainer == null)
{
// See if we can fetch from the correct list.
if (relevantStorage.Count > 0)
{
args.ItemContainer = relevantStorage[0] as SelectorItem;
}
else
{
// There aren't any recycled ItemContainers available, so a new one
// needs to be created.
ListViewItem item = new ListViewItem();
item.ContentTemplate = this.Resources[tag] as DataTemplate;
item.Tag = tag;
args.ItemContainer = item;
}
}
}
Itemsjabloonkiezer
Met een itemsjabloonkiezer (DataTemplateSelector) kan een app tijdens runtime een andere itemsjabloon retourneren op basis van het type gegevensitem dat wordt weergegeven. Dit maakt ontwikkeling productiever, maar het maakt ui-virtualisatie moeilijker omdat niet elke itemsjabloon opnieuw kan worden gebruikt voor elk gegevensitem.
Bij het recyclen van een item (ListViewItem of GridViewItem) moet het framework bepalen of de items die beschikbaar zijn voor gebruik in de prullenbakwachtrij een itemsjabloon hebben die overeenkomt met het item dat door het huidige gegevensitem wordt gebruikt. Als er geen items in de prullenbakwachtrij staan met de juiste sjabloon voor het item, wordt er een nieuw item aangemaakt en wordt de juiste sjabloon voor het item gegenereerd. Als de prullenbak daarentegen een item met de juiste itemsjabloon bevat, wordt dat item verwijderd uit de prullenbak en wordt gebruikt voor het huidige gegevensitem. Een itemsjabloonkiezer werkt in situaties waarin slechts een klein aantal itemsjablonen wordt gebruikt en er een platte distributie is in de hele verzameling items die verschillende itemsjablonen gebruiken. Wanneer er sprake is van een ongelijke verdeling van items die gebruikmaken van verschillende itemsjablonen, moeten er waarschijnlijk nieuwe itemsjablonen worden gemaakt tijdens het pannen, en dit negeert veel van de voordelen die worden geboden door virtualisatie. Daarnaast beschouwt een itemsjabloonkiezer slechts vijf mogelijke kandidaten bij het evalueren of een bepaalde container opnieuw kan worden gebruikt voor het huidige gegevensitem. U moet dus zorgvuldig overwegen of uw gegevens geschikt zijn voor gebruik met een itemsjabloonkiezer voordat u er een in uw WinUI-app gebruikt. Als uw verzameling voornamelijk homogeen is, retourneert de selector meestal hetzelfde type of altijd. Houd rekening met de kosten die je betaalt voor de zeldzame uitzonderingen op die homogeniteit en overweeg of het gebruik van ChoosingItemContainer of twee itemsbesturingselementen de voorkeur heeft.
Windows developer