Optimisation des options d’interface ListView et GridViewListView and GridView UI optimization

Remarque   Pour plus d’informations, voir la session //build/ Accroître considérablement les performances lors de l’interaction des utilisateurs avec de grandes quantités de données dans GridView et ListView.Note   For more details, see the //build/ session Dramatically Increase Performance when Users Interact with Large Amounts of Data in GridView and ListView.

Améliorez les performances des contrôles ListView et GridView et le temps de démarrage à travers la virtualisation de l’interface utilisateur, la réduction des éléments et la mise à jour progressive des éléments.Improve ListView and GridView performance and startup time through UI virtualization, element reduction, and progressive updating of items. Pour découvrir les techniques de la virtualisation des données, voir la virtualisation des données ListView et GridView.For data virtualization techniques, see ListView and GridView data virtualization.

Deux facteurs de performances clés pour les collectionsTwo key factors in collection performance

La manipulation des collections est un scénario courant.Manipulating collections is a common scenario. Une visionneuse de photos présente des collections de photos, un lecteur des collections d’articles/ouvrages/histoires et une application d’achat des collections de produits.A photo viewer has collections of photos, a reader has collections of articles/books/stories, and a shopping app has collections of products. Cette rubrique vous explique comment faire pour que votre application manipule efficacement les collections.This topic shows what you can do to make your app efficient at manipulating collections.

Il existe deux facteurs de performances clés en matière de collections : le temps que met le thread d’interface utilisateur à créer les éléments et la mémoire utilisée par le jeu de données brutes et les éléments d’interface utilisateur pour le rendu de ces données.There are two key factors in performance when it comes to collections: one is the time spent by the UI thread creating items; the other is the memory used by both the raw data set and the UI elements used to render that data.

Pour garantir des panoramiques/défilements fluides, il est essentiel que le thread d’interface utilisateur effectue l’instanciation, la liaison de données et la disposition des éléments de manière efficace et intelligente.For smooth panning/scrolling, it's vital that the UI thread do an efficient and smart job of instantiating, data-binding, and laying out items.

Virtualisation de l’interface utilisateurUI virtualization

La virtualisation de l’interface utilisateur est le principal axe d’amélioration.UI virtualization is the most important improvement you can make. Elle implique la création à la demande des éléments d’interface utilisateur.This means that UI elements representing the items are created on demand. Pour un contrôle d’éléments lié à une collection de 1 000 éléments, créer l’interface utilisateur simultanément pour tous les éléments constituerait un gaspillage de ressources, car il n’est pas possible d’afficher tous les éléments en même temps.For an items control bound to a 1000-item collection, it would be a waste of resources to create the UI for all the items at the same time, because they can't all be displayed at the same time. Les contrôles ListView et GridView (et d’autres contrôles standard dérivés de ItemsControl) se chargent de la virtualisation de l’interface utilisateur à votre place.ListView and GridView (and other standard ItemsControl-derived controls) perform UI virtualization for you. Quand des éléments vont bientôt défiler dans l’affichage (quelques pages plus loin), l’infrastructure génère l’interface utilisateur pour ces éléments et les met en cache.When items are close to being scrolled into view (a few pages away), the framework generates the UI for the items and caches them. Lorsqu’il est peu probable que les éléments soient de nouveau affichés, l’infrastructure récupère la mémoire qui leur était allouée.When it's unlikely that the items will be shown again, the framework re-claims the memory.

Si vous fournissez un modèle de panneau d’éléments personnalisé (voir ItemsPanel), veillez à utiliser un volet de virtualisation tel que ItemsWrapGrid ou ItemsStackPanel.If you provide a custom items panel template (see ItemsPanel) then make sure you use a virtualizing panel such as ItemsWrapGrid or ItemsStackPanel. Si vous utilisez VariableSizedWrapGrid, WrapGrid ou StackPanel, vous ne pourrez pas bénéficier de la virtualisation.If you use VariableSizedWrapGrid, WrapGrid, or StackPanel, then you will not get virtualization. Par ailleurs, les événements ListView suivants sont déclenchés uniquement lors de l’utilisation d’un ItemsWrapGrid ou d’un ItemsStackPanel : ChoosingGroupHeaderContainer, ChoosingItemContainer et ContainerContentChanging.Additionally, the following ListView events are raised only when using an ItemsWrapGrid or an ItemsStackPanel: ChoosingGroupHeaderContainer, ChoosingItemContainer, and ContainerContentChanging.

La fenêtre d’affichage est un concept essentiel de la virtualisation de l’interface utilisateur, car l’infrastructure doit créer les éléments qui sont susceptibles d’être affichés.The concept of a viewport is critical to UI virtualization because the framework must create the elements that are likely to be shown. La fenêtre d’affichage d’un contrôle ItemsControl est généralement l’extension du contrôle logique.In general, the viewport of an ItemsControl is the extent of the logical control. Par exemple, la fenêtre d’affichage d’un contrôle ListView correspond à la largeur et à la hauteur de l’élément ListView.For example, the viewport of a ListView is the width and height of the ListView element. Certains volets offrent un espace illimité aux éléments enfants (par exemple, ScrollViewer et Grid) avec un dimensionnement automatique des lignes ou des colonnes.Some panels allow child elements unlimited space, examples being ScrollViewer and a Grid, with auto-sized rows or columns. Lorsqu’un contrôle ItemsControl virtualisé est placé dans un volet de ce type, il occupe suffisamment d’espace pour afficher tous ses éléments, ce qui va à l’encontre de la virtualisation.When a virtualized ItemsControl is placed in a panel like that, it takes enough room to display all of its items, which defeats virtualization. Restaurez la virtualisation en définissant une largeur et une hauteur pour ItemsControl.Restore virtualization by setting a width and height on the ItemsControl.

Réduction des éléments par élémentElement reduction per item

Limitez les éléments d’interface utilisateur utilisés pour afficher vos éléments à un nombre raisonnable.Keep the number of UI elements used to render your items to a reasonable minimum.

Lorsqu’un contrôle d’éléments est affiché pour la première fois, tous les éléments nécessaires au rendu d’une fenêtre d’affichage remplie d’éléments sont créés.When an items control is first shown, all the elements needed to render a viewport full of items are created. De plus, à mesure que les éléments approchent de la fenêtre d’affichage, l’infrastructure met à jour les éléments d’interface utilisateur dans les modèles d’éléments mis en cache avec les objets de données liées.Also, as items approach the viewport, the framework updates the UI elements in cached item templates with the bound data objects. Réduire la complexité du balisage à l’intérieur des modèles est payant en termes de mémoire utilisée et de temps passé sur le thread d’interface utilisateur, avec une amélioration de la réactivité particulièrement notable lors des panoramiques/défilements.Minimizing the complexity of the markup inside templates pays off in memory and in time spent on the UI thread, improving responsiveness especially while panning/scrolling. Les modèles en question sont le modèle d’éléments (voir ItemTemplate) et le modèle de contrôle d’un élément ListViewItem ou GridViewItem (le modèle de contrôle d’éléments, ou ItemContainerStyle).The templates in question are the item template (see ItemTemplate) and the control template of a ListViewItem or a GridViewItem (the item control template, or ItemContainerStyle). L’avantage d’une réduction même minime du nombre d’éléments est multiplié par le nombre d’éléments affichés.The benefit of even a small reduction in element count is multiplied by the number of items displayed.

Pour obtenir des exemples de réduction des éléments, voirOptimiser votre balisage XAML.For examples of element reduction, see Optimize your XAML markup.

Les modèles de contrôle par défaut pour ListViewItem et GridViewItem contiennent un élément ListViewItemPresenter.The default control templates for ListViewItem and GridViewItem contain a ListViewItemPresenter element. Ce présentateur constitue un élément optimisé unique qui affiche des effets visuels complexes pour le focus, la sélection et d’autres états visuels.This presenter is a single optimized element that displays complex visuals for focus, selection, and other visual states. Si vous disposez déjà de modèles de contrôle d’éléments personnalisés (ItemContainerStyle) ou si vous modifiez par la suite une copie d’un modèle de contrôle d’éléments, nous vous recommandons d’utiliser un présentateur ListViewItemPresenter car cet élément vous offrira dans la plupart des cas un équilibre optimal entre performances et possibilités de personnalisation.If you already have custom item control templates (ItemContainerStyle), or if in future you edit a copy of an item control template, then we recommend you use a ListViewItemPresenter because that element will give you optimum balance between performance and customizability in the majority of cases. Ce présentateur peut être personnalisé en définissant des propriétés pour lui.You customize the presenter by setting properties on it. Par exemple, voici un balisage qui supprime la coche qui s’affiche par défaut quand un élément est sélectionné, puis remplace la couleur d’arrière-plan de l’élément sélectionné par la couleur orange.For example, here's markup that removes the check mark that appears by default when an item is selected, and changes the background color of the selected item to orange.

...
<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>
<!-- ... -->

Il y a environ 25 propriétés portant des noms autodescriptifs similaires à SelectionCheckMarkVisualEnabled et SelectedBackground.There are about 25 properties with self-describing names similar to SelectionCheckMarkVisualEnabled and SelectedBackground. Si les types de présentateur se révèlent ne pas être suffisamment personnalisables pour votre cas d’utilisation, vous pouvez modifier une copie du modèle de contrôle ListViewItemExpanded ou GridViewItemExpanded à la place.Should the presenter types prove not to be customizable enough for your use case, you can edit a copy of the ListViewItemExpanded or GridViewItemExpanded control template instead. Ces modèles se trouvent dans \Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<version>\Generic\generic.xaml.These can be found in \Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<version>\Generic\generic.xaml. Notez que l’utilisation de ces modèles implique un compromis en termes de performances en échange de l’augmentation des possibilités de personnalisation.Be aware that using these templates means trading some performance for the increase in customization.

Mettre à jour les éléments ListView et GridView de façon progressiveUpdate ListView and GridView items progressively

Si vous utilisez la virtualisation des données, vous pouvez maintenir la réactivité de ListView et GridView élevée en configurant le contrôle de façon à afficher des éléments d’interface utilisateur temporaires à la place des éléments encore en cours de (télé)chargement.If you're using data virtualization then you can keep ListView and GridView responsiveness high by configuring the control to render temporary UI elements for the items still being (down)loaded. Les éléments temporaires sont ensuite progressivement remplacés par l’interface utilisateur réelle à mesure que les données sont chargées.The temporary elements are then progressively replaced with actual UI as data loads.

De plus, quelle que soit votre source de chargement des données (disque local, réseau ou cloud), il se peut qu’un utilisateur parcoure un contrôle ListView ou GridView si rapidement qu’il est impossible d’afficher chaque élément avec une fidélité totale tout en préservant la fluidité des panoramiques/défilements.Also—no matter where you're loading data from (local disk, network, or cloud)—a user can pan/scroll a ListView or GridView so rapidly that it's not possible to render each item with full fidelity while preserving smooth panning/scrolling. Pour préserver la fluidité des panoramiques/défilements, vous pouvez choisir d’afficher un élément par phases en plus d’utiliser des espaces réservés.To preserve smooth panning/scrolling you can choose to render an item in multiple phases in addition to using placeholders.

Ce type de techniques est souvent utilisé dans les applications de visionnage de photos : même si toutes les images n’ont pas été chargées et affichées, l’utilisateur peut toujours les parcourir à l’aide de panoramiques/défilements et interagir avec la collection.An example of these techniques is often seen in photo-viewing apps: even though not all of the images have been loaded and displayed, the user can still pan/scroll and interact with the collection. Ou, dans le cas d’un élément « film », vous pouvez afficher le titre à la première phase, la note à la deuxième et une image de l’affiche à la troisième.Or, for a "movie" item, you could show the title in the first phase, the rating in the second phase, and an image of the poster in the third phase. L’utilisateur a accès aux données les plus importantes sur chaque élément le plus tôt possible, ce qui signifie qu’il est en mesure d’effectuer une action immédiatement.The user sees the most important data about each item as early as possible, and that means they're able to take action at once. Les informations moins importantes sont ensuite renseignées au fur et à mesure.Then the less important info is filled-in as time allows. Voici les fonctionnalités de plateforme que vous pouvez utiliser pour implémenter ces techniques.Here are the platform features you can use to implement these techniques.

Espaces réservésPlaceholders

La fonctionnalité d’espaces réservés visuels temporaires est activée par défaut et est contrôlée par la propriété ShowsScrollingPlaceholders.The temporary placeholder visuals feature is on by default, and it's controlled with the ShowsScrollingPlaceholders property. Pendant les panoramiques/défilements rapides, cette fonctionnalité indique de façon visuelle à l’utilisateur que certains éléments ne sont pas encore complètement affichés, tout en préservant la fluidité de l’expérience.During fast panning/scrolling, this feature gives the user a visual hint that there are more items yet to fully display while also preserving smoothness. Si vous utilisez une des techniques ci-dessous, vous pouvez définir ShowsScrollingPlaceholders sur False si vous ne souhaitez pas que le système restitue les espaces réservés.If you use one of the techniques below then you can set ShowsScrollingPlaceholders to false if you prefer not to have the system render placeholders.

Mises à jour de modèles de données progressives avec x:PhaseProgressive data template updates using x:Phase

Voici comment utiliser l’attribut x:Phase avec les liaisons {x:Bind} pour implémenter des mises à jour de modèles de données progressives.Here's how to use the x:Phase attribute with {x:Bind} bindings to implement progressive data template updates.

  1. Voici à quoi ressemble la source de liaison (il s’agit de la source de données que nous allons lier) :Here's what the binding source looks like (this is the data source that we'll bind to).

    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()
                    });
                }
            }
        }
    }
    
  2. Voici le balisage que contient le fichier DeferMainPage.xaml.Here's the markup that DeferMainPage.xaml contains. L’affichage grille contient un modèle d’élément avec des éléments liés aux propriétés Title, Subtitle et Description de la classe MyItem.The grid view contains an item template with elements bound to the Title, Subtitle, and Description properties of the MyItem class. Notez que x:Phase a pour valeur par défaut 0.Note that x:Phase defaults to 0. Ici, les éléments sont affichés initialement avec seulement le titre visible.Here, items will be initially rendered with just the title visible. L’élément sous-titre est ensuite lié aux données et affiché pour tous les éléments, et ainsi de suite jusqu’à ce que toutes les phases aient été traitées.Then the subtitle element will be data bound and made visible for all the items and so on until all the phases have been processed.

    <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>
    
  3. Si vous exécutez l’application maintenant et que vous parcourez rapidement l’affichage grille à l’aide de panoramiques/défilements, vous remarquerez que lorsque chaque nouvel élément apparaît à l’écran, il est tout d’abord affiché sous forme de rectangle gris foncé (grâce à la propriété ShowsScrollingPlaceholders par défaut true), puis le titre s’affiche, suivi du sous-titre, puis d’une description.If you run the app now and pan/scroll quickly through the grid view then you'll notice that as each new item appears on the screen, at first it is rendered as a dark gray rectangle (thanks to the ShowsScrollingPlaceholders property defaulting to true), then the title appears, followed by subtitle, followed by description.

Mises à jour de modèles de données progressives avec ContainerContentChangingProgressive data template updates using ContainerContentChanging

La stratégie générale pour l’événement ContainerContentChanging consiste à utiliser Opacity pour masquer les éléments qui n’ont pas besoin d’être immédiatement visibles.The general strategy for the ContainerContentChanging event is to use Opacity to hide elements that don’t need to be immediately visible. Lorsque les éléments sont recyclés, ils conservent leurs anciennes valeurs. C’est pourquoi nous souhaitons masquer ces éléments jusqu’à ce que nous ayons mis à jour ces valeurs à partir du nouvel élément de données.When elements are recycled, they will retain their old values so we want to hide those elements until we've updated those values from the new data item. Nous utilisons la propriété Phase sur les arguments d’événement pour déterminer les éléments à mettre à jour et à afficher.We use the Phase property on the event arguments to determine which elements to update and show. Si des phases supplémentaires sont nécessaires, nous inscrivons un rappel.If additional phases are needed, we register a callback.

  1. Nous utilisons la même source de liaison que pour x:Phase.We'll use the same binding source as for x:Phase.

  2. Voici le balisage que contient le fichier MainPage.xaml.Here's the markup that MainPage.xaml contains. L’affichage grille déclare un gestionnaire à son événement ContainerContentChanging et contient un modèle d’élément avec des éléments utilisés pour afficher les propriétés Title, Subtitle et Description de la classe MyItem.The grid view declares a handler to its ContainerContentChanging event, and it contains an item template with elements used to display the Title, Subtitle, and Description properties of the MyItem class. Pour exploiter pleinement les avantages de ContainerContentChanging en termes de performances, nous n’utilisons pas de liaisons dans le balisage, mais nous attribuons à la place des valeurs par programme.To get the maximum performance benefits of using ContainerContentChanging, we don't use bindings in the markup but we instead assign values programmatically. L’exception ici est l’élément affichant le titre, que nous considérons dans la phase 0.The exception here is the element displaying the title, which we consider to be in phase 0.

    <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>
    
  3. Enfin, voici l’implémentation du gestionnaire d’événements ContainerContentChanging.Lastly, here's the implementation of the ContainerContentChanging event handler. Ce code montre également comment nous ajoutons une propriété de type RecordingViewModel à MainPage pour exposer la classe de source de liaison à partir de la classe qui représente notre page de balisage.This code also shows how we add a property of type RecordingViewModel to MainPage to expose the binding source class from the class that represents our page of markup. À condition que votre modèle de données ne comporte aucune liaison {Binding}, marquez l’objet arguments d’événement comme géré dans la première phase du gestionnaire pour indiquer à l’élément qu’il n’a pas besoin de définir un contexte de données.As long as you don't have any {Binding} bindings in your data template, then mark the event arguments object as handled in the first phase of the handler to hint to the item that it needn't set a data context.

    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;
            }
        }
    }
    
  4. Si vous exécutez l’application maintenant et que vous parcourez rapidement l’affichage grille à l’aide de panoramiques/défilements, vous observerez le même comportement que pour x:Phase.If you run the app now and pan/scroll quickly through the grid view then you'll see the same behavior as for as for x:Phase.

Recyclage de conteneurs avec des collections hétérogènesContainer-recycling with heterogeneous collections

Dans certaines applications, vous devez avoir différentes interfaces utilisateur pour différents types d’élément au sein d’une collection.In some applications, you need to have different UI for different types of item within a collection. Cela peut créer une situation dans laquelle il est impossible pour les volets de virtualisation de réutiliser/recycler les éléments visuels utilisés pour afficher les éléments.This can create a situation where it is impossible for virtualizing panels to reuse/recycle the visual elements used to display the items. La recréation des éléments visuels d’un élément pendant le mouvement panoramique annule bon nombre des gains de performances offerts par la virtualisation.Recreating the visual elements for an item during panning undoes many of the performance wins provided by virtualization. Cependant, un minimum de planification peut permettre aux volets de virtualisation de réutiliser les éléments.However, a little planning can allow virtualizing panels to reuse the elements. Les développeurs ont deux options en fonction de leur scénario : l’événement ChoosingItemContainer ou un sélecteur de modèles d’éléments.Developers have a couple of options depending on their scenario: the ChoosingItemContainer event, or an item template selector. L’approche ChoosingItemContainer offre de meilleures performances.The ChoosingItemContainer approach has better performance.

Événement ChoosingItemContainerThe ChoosingItemContainer event

ChoosingItemContainer est un événement qui vous permet de fournir un élément (ListViewItem/GridViewItem) à la ListView/GridView chaque fois qu’un nouvel élément est nécessaire au cours de démarrage ou du recyclage.ChoosingItemContainer is an event that allows you to provide an item (ListViewItem/GridViewItem) to the ListView/GridView whenever a new item is needed during start-up or recycling. Vous pouvez créer un conteneur basé sur le type d’élément de données affiché par le conteneur (illustré dans l’exemple ci-dessous).You can create a container based on the type of data item the container will display (shown in the example below). ChoosingItemContainer est la méthode la plus performante pour utiliser différents modèles de données pour différents éléments.ChoosingItemContainer is the higher-performing way to use different data templates for different items. La mise en cache du conteneur peut être obtenue avec ChoosingItemContainer.Container caching is something that can be achieved using ChoosingItemContainer. Par exemple, si vous avez cinq modèles différents, avec un modèle présentant un ordre de grandeur plus fréquent que les autres, alors ChoosingItemContainer permet non seulement de créer des éléments dans les rapports nécessaires, mais également de conserver un nombre approprié d’éléments mis en cache et disponibles pour le recyclage.For example, if you have five different templates, with one template occurring an order of magnitude more often than the others, then ChoosingItemContainer allows you not only to create items at the ratios needed but also to keep an appropriate number of elements cached and available for recycling. ChoosingGroupHeaderContainer fournit les mêmes fonctionnalités pour les en-têtes de groupe.ChoosingGroupHeaderContainer provides the same functionality for group headers.

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

Sélecteur de modèles d’élémentsItem template selector

Un sélecteur de modèles d’éléments (DataTemplateSelector) permet à une application de renvoyer un modèle d’élément différent lors de l’exécution en fonction du type de l’élément de données qui sera affiché.An item template selector (DataTemplateSelector) allows an app to return a different item template at runtime based on the type of the data item that will be displayed. Cela rend le développement plus productif, mais la virtualisation de l’interface utilisateur plus difficile, car chaque modèle d’élément ne peut pas être réutilisé pour chaque élément de données.This makes development more productive, but it makes UI virtualization more difficult because not every item template can be reused for every data item.

Lors du recyclage d’un élément (ListViewItem/GridViewItem), l’infrastructure doit décider si les éléments qui sont disponibles pour utilisation dans la file d’attente de recyclage (la file d’attente de recyclage est un cache d’éléments qui ne sont pas utilisés pour afficher des données) disposent d’un modèle d’élément qui correspond à celui souhaité par l’élément de données en cours.When recycling an item (ListViewItem/GridViewItem), the framework must decide whether the items that are available for use in the recycle queue (the recycle queue is a cache of items that are not currently being used to display data) have an item template that will match the one desired by the current data item. S’il n’y a aucun élément dans la file d’attente de recyclage avec le modèle d’élément approprié, alors un nouvel élément est créé, et le modèle d’élément approprié est instancié pour celui-ci.If there are no items in the recycle queue with the appropriate item template then a new item is created, and the appropriate item template is instantiated for it. Si, d’autre part, la file d’attente de recyclage contient un élément avec le modèle d’élément approprié, alors cet élément est supprimé de la file d’attente de recyclage et est utilisé pour l’élément de données actuel.If, on other hand, the recycle queue contains an item with the appropriate item template then that item is removed from the recycle queue and is used for the current data item. Un sélecteur de modèles d’éléments est adapté lorsque seul un petit nombre de modèles d’éléments est utilisé et qu’il existe une répartition homogène dans la collection d’éléments utilisant différents modèles d’éléments.An item template selector works in situations where only a small number of item templates are used and there is a flat distribution throughout the collection of items that use different item templates.

Lorsque la répartition des éléments utilisant différents modèles d’éléments est inégale, alors les modèles d’éléments devront probablement être créés lors du mouvement panoramique, annulant ainsi nombre des avantages offerts par la virtualisation.When there is an uneven distribution of items that use different item templates then new item templates will likely need to be created during panning, and this negates many of the gains provided by virtualization. En outre, un sélecteur de modèles d’éléments ne considère que cinq candidats possibles lorsqu’il s’agit d’évaluer si un conteneur donné peut être réutilisé pour l’élément de données actuel.Additionally, an item template selector only considers five possible candidates when evaluating whether a particular container can be reused for the current data item. Par conséquent, il convient d’examiner attentivement vos données pour déterminer si elles sont appropriées pour une utilisation avec un sélecteur de modèles d’éléments avant d’en utiliser un dans votre application.So you should carefully consider whether your data is appropriate for use with an item template selector before using one in your app. Si votre collection est en grande partie homogène, le sélecteur renvoie le même type la plupart du temps (voire tout le temps).If your collection is mostly homogeneous then the selector is returning the same type most (possibly all) of the time. Soyez conscient du prix que vous payez pour les exceptions à cette homogénéité et demandez-vous s’il est préférable d’utiliser ChoosingItemContainer (ou deux contrôles d’éléments).Just be aware of the price you're paying for the rare exceptions to that homegeneity, and consider whether using ChoosingItemContainer (or two items controls) is preferable.