ListView

Browse sample. Esplorare l'esempio

L'interfaccia utente dell'app multipiattaforma .NET (.NET MAUI) ListView visualizza un elenco verticale scorrevole di elementi di dati selezionabili. Mentre ListView gestisce l'aspetto dell'elenco, l'aspetto di ogni elemento nell'elenco è definito da un DataTemplate oggetto che usa un Cell oggetto per visualizzare gli elementi. .NET MAUI include tipi di cella per visualizzare combinazioni di testo e immagini ed è anche possibile definire celle personalizzate che visualizzano qualsiasi contenuto desiderato. ListView include anche il supporto per la visualizzazione di intestazioni e piè di pagina, dati raggruppati, aggiornamenti pull-to-refresh e voci di menu di scelta rapida.

La ListView classe deriva dalla ItemsView<Cell> classe , da cui eredita le proprietà seguenti:

  • ItemsSource, di tipo IEnumerable, specifica la raccolta di elementi da visualizzare e ha un valore predefinito .null
  • ItemTemplate, di tipo DataTemplate, specifica il modello da applicare a ogni elemento della raccolta di elementi da visualizzare.

ListView definisce le proprietà seguenti:

  • Footer, di tipo object, specifica la stringa o la visualizzazione che verrà visualizzata alla fine dell'elenco.
  • FooterTemplate, di tipo DataTemplate, specifica l'oggetto DataTemplate da utilizzare per formattare l'oggetto Footer.
  • GroupHeaderTemplate, di tipo DataTemplate, definisce l'oggetto DataTemplate usato per definire l'aspetto dell'intestazione di ogni gruppo. Questa proprietà si escludono a vicenda con la GroupDisplayBinding proprietà . Pertanto, l'impostazione di questa proprietà verrà impostata su GroupDisplayBindingnull.
  • HasUnevenRows, di tipo bool, indica se gli elementi nell'elenco possono avere righe di altezze diverse. Il valore predefinito di questa proprietà è false.
  • Header, di tipo object, specifica la stringa o la visualizzazione che verrà visualizzata all'inizio dell'elenco.
  • HeaderTemplate, di tipo DataTemplate, specifica l'oggetto DataTemplate da utilizzare per formattare l'oggetto Header.
  • HorizontalScrollBarVisibility, di tipo ScrollBarVisibility, indica quando la barra di scorrimento orizzontale sarà visibile.
  • IsGroupedEnabled, di tipo bool, indica se i dati sottostanti devono essere visualizzati in gruppi. Il valore predefinito di questa proprietà è false.
  • IsPullToRefreshEnabled, di tipo bool, indica se l'utente può scorrere verso il basso per fare in modo che l'oggetto ListView aggiorni i dati. Il valore predefinito di questa proprietà è false.
  • IsRefreshing, di tipo bool, indica se l'oggetto ListView è attualmente aggiornato. Il valore predefinito di questa proprietà è false.
  • RefreshCommand, di tipo ICommand, rappresenta il comando che verrà eseguito quando viene attivato un aggiornamento.
  • RefreshControlColor, di tipo Color, determina il colore della visualizzazione di aggiornamento visualizzata mentre si verifica un aggiornamento.
  • RowHeight, di tipo int, determina l'altezza di ogni riga quando HasUnevenRows è false.
  • SelectedItem, di tipo object, rappresenta l'elemento attualmente selezionato in ListView.
  • SelectionMode, di tipo ListViewSelectionMode, indica se gli elementi possono essere selezionati in ListView o meno. Il valore predefinito di questa proprietà è Single.
  • SeparatorColor, di tipo Color, definisce il colore della barra che separa gli elementi nell'elenco.
  • SeparatorVisibility, di tipo SeparatorVisibility, definisce se i separatori sono visibili tra gli elementi.
  • VerticalScrollBarVisibility, di tipo ScrollBarVisibility, indica quando la barra di scorrimento verticale sarà visibile.

Tutte queste proprietà sono supportate da BindableProperty oggetti, il che significa che possono essere destinazioni di data binding e stili.

Definisce inoltre ListView le proprietà seguenti che non sono supportate dagli BindableProperty oggetti :

  • GroupDisplayBinding, di tipo BindingBase, associazione da usare per visualizzare l'intestazione del gruppo. Questa proprietà si escludono a vicenda con la GroupHeaderTemplate proprietà . Pertanto, l'impostazione di questa proprietà verrà impostata su GroupHeaderTemplatenull.
  • GroupShortNameBinding, di tipo BindingBase, l'associazione per il nome da visualizzare in jump list raggruppate.
  • CachingStrategy, di tipo ListViewCachingStrategy, definisce la strategia di riutilizzo delle celle di ListView. Questa proprietà è di sola lettura.

ListView definisce gli eventi seguenti:

  • ItemAppearing, generato quando viene aggiunta la rappresentazione visiva di un elemento al layout visivo dell'oggetto ListView. L'oggetto ItemVisibilityEventArgs che accompagna questo evento definisce Item le proprietà e Index .
  • ItemDisappearing, generato quando la rappresentazione visiva di un elemento viene rimossa dal layout visivo dell'oggetto ListView. L'oggetto ItemVisibilityEventArgs che accompagna questo evento definisce Item le proprietà e Index .
  • ItemSelected, generato quando viene selezionato un nuovo elemento nell'elenco. L'oggetto SelectedItemChangedEventArgs che accompagna questo evento definisce SelectedItem le proprietà e SelectedItemIndex .
  • ItemTapped, generato quando viene toccato un elemento nell'oggetto ListView . L'oggetto ItemTappedEventArgs che accompagna questo evento definisce Grouple proprietà , Iteme ItemIndex .
  • Refreshing, generato quando viene attivata un'operazione pull per l'aggiornamento in ListView.
  • Scrolled, . L'oggetto ScrolledEventArgs che accompagna questo evento definisce ScrollX le proprietà e ScrollY .
  • ScrollToRequested . L'oggetto ScrollToRequestedEventArgs che accompagna questo evento definisce Elementle proprietà , PositionMode, ScrollYScrollX, , e ShouldAnimate .

Popolare un controllo ListView con i dati

Un ListView oggetto viene popolato con i dati impostando la relativa ItemsSource proprietà su qualsiasi raccolta che implementa IEnumerable.

Importante

ListView Se è necessario aggiornare quando vengono aggiunti, rimossi o modificati elementi nella raccolta sottostante, la raccolta sottostante deve essere una IEnumerable raccolta che invia notifiche di modifica delle proprietà, ad esempio ObservableCollection.

ListView può essere popolato con i dati usando il data binding per associarne la ItemsSource proprietà a una IEnumerable raccolta. In XAML questo risultato viene ottenuto con l'estensione di Binding markup:

<ListView ItemsSource="{Binding Monkeys}" />

Il codice C# equivalente è il seguente:

ListView listView = new ListView();
listView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

In questo esempio, i dati della ItemsSource proprietà vengono associati alla Monkeys proprietà del modello di visualizzazione connesso.

Nota

Le associazioni compilate possono essere abilitate per migliorare le prestazioni del data binding nelle applicazioni MAUI .NET. Per altre informazioni, vedere Binding compilati.

Per altre informazioni sul data binding, vedere Data binding.

Definire l'aspetto dell'elemento

L'aspetto di ogni elemento in ListView può essere definito impostando la ItemTemplate proprietà su :DataTemplate

<ListView ItemsSource="{Binding Monkeys}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid Padding="10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Image Grid.RowSpan="2"
                           Source="{Binding ImageUrl}"
                           Aspect="AspectFill"
                           HeightRequest="60"
                           WidthRequest="60" />
                    <Label Grid.Column="1"
                           Text="{Binding Name}"
                           FontAttributes="Bold" />
                    <Label Grid.Row="1"
                           Grid.Column="1"
                           Text="{Binding Location}"
                           FontAttributes="Italic"
                           VerticalOptions="End" />
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Gli elementi specificati nell'oggetto DataTemplate definiscono l'aspetto di ogni elemento nell'elenco e l'elemento figlio di DataTemplate deve essere un Cell oggetto . Nell'esempio il layout all'interno di DataTemplate è gestito da un oggetto Grid. Grid Contiene un Image oggetto e due Label oggetti, che vengono associati alle proprietà della Monkey classe :

public class Monkey
{
    public string Name { get; set; }
    public string Location { get; set; }
    public string Details { get; set; }
    public string ImageUrl { get; set; }
}

Lo screenshot seguente mostra il risultato della creazione di modelli per ogni elemento nell'elenco:

Screenshot of ListView where each item is templated.

Per altre informazioni sui modelli di dati, vedere Modelli di dati.

Cells

L'aspetto di ogni elemento in un ListView oggetto è definito da un DataTemplateoggetto e DataTemplate deve fare riferimento a una Cell classe per visualizzare gli elementi. Ogni cella rappresenta un elemento di dati nell'oggetto ListView. .NET MAUI include le celle predefinite seguenti:

  • TextCell, che visualizza il testo primario e secondario in righe separate.
  • ImageCell, che visualizza un'immagine con testo primario e secondario su righe separate.
  • SwitchCell, che visualizza il testo e un interruttore che può essere attivato o disattivato.
  • EntryCell, che visualizza un'etichetta e un testo modificabili.
  • ViewCell, ovvero una cella personalizzata il cui aspetto è definito da un oggetto View. Questo tipo di cella deve essere usato quando si desidera definire completamente l'aspetto di ogni elemento in un oggetto ListView.

In genere, SwitchCell e EntryCell verranno usati solo in e TableView non verranno usati in un oggetto ListView. Per altre informazioni su SwitchCell e EntryCell, vedere TableView.

Cella di testo

Un TextCell oggetto visualizza il testo primario e secondario su righe separate. TextCell definisce le proprietà seguenti:

  • Text, di tipo string, definisce il testo primario da visualizzare.
  • TextColor, di tipo Color, rappresenta il colore del testo primario.
  • Detail, di tipo string, definisce il testo secondario da visualizzare.
  • DetailColor, di tipo Color, indica il colore del testo secondario.
  • Command, di tipo ICommand, definisce il comando eseguito quando viene toccata la cella.
  • CommandParameter, di tipo object, rappresenta il parametro passato al comando .

Queste proprietà sono supportate da BindableProperty oggetti, il che significa che possono essere destinazioni di data binding e stili.

Nell'esempio seguente viene illustrato l'uso di per TextCell definire l'aspetto degli elementi in un ListViewoggetto :

<ListView ItemsSource="{Binding Food}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextCell Text="{Binding Name}"
                      Detail="{Binding Description}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Lo screenshot seguente mostra l'aspetto della cella risultante:

Screenshot of ListView where each item is a TextCell.

Cella Image

Un ImageCell oggetto visualizza un'immagine con testo primario e secondario su righe separate. ImageCell eredita le proprietà da TextCelle definisce la ImageSource proprietà di tipo ImageSource, che specifica l'immagine da visualizzare nella cella. Questa proprietà è supportata da un BindableProperty oggetto , il che significa che può essere la destinazione dei data binding e essere stilizzato.

Nell'esempio seguente viene illustrato l'uso di un ImageCell oggetto per definire l'aspetto degli elementi in un ListViewoggetto :

<ListView ItemsSource="{Binding Food}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ImageCell ImageSource="{Binding Image}"
                       Text="{Binding Name}"
                       Detail="{Binding Description}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Lo screenshot seguente mostra l'aspetto della cella risultante:

Screenshot of ListView where each item is an ImageCell.

Visualizzare la cella

Un ViewCell oggetto è una cella personalizzata il cui aspetto è definito da un oggetto View. ViewCell definisce una View proprietà di tipo View, che definisce la visualizzazione che rappresenta il contenuto della cella. Questa proprietà è supportata da un BindableProperty oggetto , il che significa che può essere la destinazione dei data binding e essere stilizzato.

Nota

La View proprietà è la proprietà content della ViewCell classe e pertanto non deve essere impostata in modo esplicito da XAML.

Nell'esempio seguente viene illustrato l'uso di per ViewCell definire l'aspetto degli elementi in un ListViewoggetto :

<ListView ItemsSource="{Binding Monkeys}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid Padding="10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Image Grid.RowSpan="2"
                           Source="{Binding ImageUrl}"
                           Aspect="AspectFill"
                           HeightRequest="60"
                           WidthRequest="60" />
                    <Label Grid.Column="1"
                           Text="{Binding Name}"
                           FontAttributes="Bold" />
                    <Label Grid.Row="1"
                           Grid.Column="1"
                           Text="{Binding Location}"
                           FontAttributes="Italic"
                           VerticalOptions="End" />
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

All'interno di , il ViewCelllayout può essere gestito da qualsiasi layout MAUI .NET. In questo esempio il layout viene gestito da un oggetto Grid. Grid Contiene un Image oggetto e due Label oggetti associati alle proprietà della Monkey classe .

Lo screenshot seguente mostra il risultato della creazione di modelli per ogni elemento nell'elenco:

Screenshot of ListView where each item is templated with a ViewCell.

Scegliere l'aspetto dell'elemento in fase di esecuzione

L'aspetto di ogni elemento in può essere scelto in ListView fase di esecuzione, in base al valore dell'elemento, impostando la ItemTemplate proprietà su un DataTemplateSelector oggetto :

<ContentPage ...
             xmlns:templates="clr-namespace:ListViewDemos.Templates">
    <ContentPage.Resources>
        <DataTemplate x:Key="AmericanMonkeyTemplate">
            <ViewCell>
                ...
            </ViewCell>
        </DataTemplate>

        <DataTemplate x:Key="OtherMonkeyTemplate">
            <ViewCell>
                ...
            </ViewCell>
        </DataTemplate>

        <templates:MonkeyDataTemplateSelector x:Key="MonkeySelector"
                                             AmericanMonkey="{StaticResource AmericanMonkeyTemplate}"
                                             OtherMonkey="{StaticResource OtherMonkeyTemplate}" />
    </ContentPage.Resources>

    <StackLayout Margin="20">
        <ListView ItemsSource="{Binding Monkeys}"
                  ItemTemplate="{StaticResource MonkeySelector}" />
    </StackLayout>
</ContentPage>

La ItemTemplate proprietà è impostata su un MonkeyDataTemplateSelector oggetto . L'esempio seguente illustra la MonkeyDataTemplateSelector classe :

public class MonkeyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate AmericanMonkey { get; set; }
    public DataTemplate OtherMonkey { get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        return ((Monkey)item).Location.Contains("America") ? AmericanMonkey : OtherMonkey;
    }
}

La MonkeyDataTemplateSelector classe definisce AmericanMonkey e OtherMonkeyDataTemplate proprietà impostate su modelli di dati diversi. L'override OnSelectTemplate restituisce il AmericanMonkey modello, che visualizza il nome della scimmia e la posizione in teal, quando il nome della scimmia contiene "America". Quando il nome della scimmia non contiene "America", l'override OnSelectTemplate restituisce il OtherMonkey modello, che visualizza il nome della scimmia e la posizione in argento:

Screenshot of ListView runtime item template selection.

Per altre informazioni sui selettori di modelli di dati, vedere Creare un oggetto DataTemplateSelector.

Rispondere alla selezione di elementi

Per impostazione predefinita, ListView la selezione è abilitata. Tuttavia, questo comportamento può essere modificato impostando la SelectionMode proprietà . L'enumerazione ListViewSelectionMode definisce i membri seguenti:

  • None – indica che non è possibile selezionare gli elementi.
  • Single : indica che è possibile selezionare un singolo elemento, con l'elemento selezionato evidenziato. Questo è il valore predefinito.

ListView definisce un ItemSelected evento generato quando la SelectedItem proprietà viene modificata, a causa della selezione di un elemento dall'elenco da parte dell'utente o quando un'app imposta la proprietà. L'oggetto SelectedItemChangedEventArgs che accompagna questo evento ha SelectedItem proprietà e SelectedItemIndex .

Quando la SelectionMode proprietà è impostata su Single, è possibile selezionare un singolo elemento in ListView . Quando si seleziona un elemento, la SelectedItem proprietà verrà impostata sul valore dell'elemento selezionato. Quando questa proprietà viene modificata, viene generato l'evento ItemSelected .

L'esempio seguente mostra un oggetto ListView in grado di rispondere alla selezione di un singolo elemento:

<ListView ItemsSource="{Binding Monkeys}"
          ItemSelected="OnItemSelected">
    ...
</ListView>

In questo esempio il OnItemSelected gestore eventi viene eseguito quando viene generato l'evento ItemSelected , con il gestore eventi che recupera l'elemento selezionato:

void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
    Monkey item = args.SelectedItem as Monkey;
}

Lo screenshot seguente mostra la selezione di un singolo elemento in un oggetto ListView:

Screenshot of a ListView with a selection.

Deselezionare la selezione

La SelectedItem proprietà può essere cancellata impostandola o l'oggetto a cui è associato, a null.

Disabilita selezione

ListView la selezione è abilitata per impostazione predefinita. Tuttavia, può essere disabilitato impostando la SelectionMode proprietà su None:

<ListView ...
          SelectionMode="None" />

Quando la SelectionMode proprietà è impostata su None, gli elementi in ListView non possono essere selezionati, la SelectedItem proprietà rimarrà nulle l'evento ItemSelected non verrà generato.

Dati cache

ListView è una visualizzazione potente per la visualizzazione dei dati, ma presenta alcune limitazioni. Le prestazioni di scorrimento possono risentire quando si usano celle personalizzate, soprattutto quando contengono gerarchie di visualizzazione annidate in profondità o si usano determinati layout che richiedono una misurazione complessa. Fortunatamente, esistono tecniche che è possibile usare per evitare prestazioni scarse.

Un ListView oggetto viene spesso usato per visualizzare molti più dati rispetto a quelli visualizzati sullo schermo. Ad esempio, un'app musicale potrebbe avere una libreria di canzoni con migliaia di voci. La creazione di un elemento per ogni voce potrebbe sprecare memoria preziosa e prestazioni scarse. La creazione e l'eliminazione costante di righe richiederebbero all'app di creare continuamente istanze e pulire gli oggetti, con prestazioni anche scarse.

Per risparmiare memoria, gli equivalenti nativi ListView per ogni piattaforma hanno funzionalità predefinite per il riutilizzo delle righe. Solo le celle visibili sullo schermo vengono caricate in memoria e il contenuto viene caricato nelle celle esistenti. Questo modello impedisce all'app di creare un'istanza di migliaia di oggetti, risparmiando tempo e memoria.

.NET MAUI consente il ListView riutilizzo delle celle tramite l'enumerazione ListViewCachingStrategy , che definisce i membri seguenti:

  • RetainElement, specifica che ListView genererà una cella per ogni elemento nell'elenco.
  • RecycleElement, specifica che ListView tenterà di ridurre al minimo il footprint di memoria e la velocità di esecuzione riciclando le celle dell'elenco.
  • RecycleElementAndDataTemplate, come RecycleElement anche per garantire che quando un utilizza un ListViewDataTemplateSelectoroggetto , DataTemplate gli oggetti vengono memorizzati nella cache in base al tipo di elemento nell'elenco.

Mantieni elementi

La RetainElement strategia di memorizzazione nella cache specifica che ListView genererà una cella per ogni elemento nell'elenco ed è il comportamento predefinito ListView . Deve essere usato nelle circostanze seguenti:

  • Ogni cella ha un numero elevato di associazioni (20-30+).
  • Il modello di cella cambia frequentemente.
  • Il test rivela che la strategia di RecycleElement memorizzazione nella cache comporta una riduzione della velocità di esecuzione.

È importante riconoscere le conseguenze della strategia di RetainElement memorizzazione nella cache quando si lavora con celle personalizzate. Qualsiasi codice di inizializzazione delle celle dovrà essere eseguito per ogni creazione di cella, che può essere più volte al secondo. In questa circostanza, le tecniche di layout che erano belle in una pagina, come l'uso di più oggetti annidati StackLayout , diventano colli di bottiglia delle prestazioni quando vengono configurati e distrutti in tempo reale mentre l'utente scorre.

Riciclare gli elementi

La RecycleElement strategia di memorizzazione nella cache specifica che ListView tenterà di ridurre al minimo il footprint di memoria e la velocità di esecuzione riciclando le celle dell'elenco. Questa modalità non offre sempre un miglioramento delle prestazioni e i test devono essere eseguiti per determinare eventuali miglioramenti. Tuttavia, è la scelta preferita e deve essere usata nelle circostanze seguenti:

  • Ogni cella ha un numero ridotto o moderato di associazioni.
  • Ogni cella BindingContext definisce tutti i dati delle celle.
  • Ogni cella è in gran parte simile, con il modello di cella che non cambia.

Durante la virtualizzazione la cella avrà aggiornato il contesto di associazione e pertanto, se un'app usa questa modalità, deve assicurarsi che gli aggiornamenti del contesto di associazione vengano gestiti in modo appropriato. Tutti i dati relativi alla cella devono provenire dal contesto di associazione o possono verificarsi errori di coerenza. Questo problema può essere evitato usando il data binding per visualizzare i dati delle celle. In alternativa, i dati delle celle devono essere impostati nell'override OnBindingContextChanged , anziché nel costruttore della cella personalizzata, come illustrato nell'esempio seguente:

public class CustomCell : ViewCell
{
    Image image = null;

    public CustomCell()
    {
        image = new Image();
        View = image;
    }

    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();

        var item = BindingContext as ImageItem;
        if (item != null)
        {
            image.Source = item.ImageUrl;
        }
    }
}

Riciclare gli elementi con un oggetto DataTemplateSelector

Quando un ListView oggetto usa un DataTemplateSelector oggetto per selezionare un DataTemplateoggetto , la RecycleElement strategia di memorizzazione nella cache non memorizza nella cache DataTemplate gli oggetti. Viene invece selezionato un oggetto DataTemplate per ogni elemento di dati nell'elenco.

Nota

La RecycleElement strategia di memorizzazione nella cache richiede che quando viene richiesto a un oggetto DataTemplateSelector di selezionare un DataTemplate oggetto che deve DataTemplate restituire lo stesso ViewCell tipo. Ad esempio, dato un ListView oggetto con che DataTemplateSelector può restituire MyDataTemplateA (dove MyDataTemplateA restituisce un ViewCell di tipo MyViewCellA) o MyDataTemplateB (dove MyDataTemplateB restituisce un ViewCell di tipo MyViewCellB), quando MyDataTemplateA viene restituito deve restituire MyViewCellA o verrà generata un'eccezione.

Riciclare gli elementi con DataTemplate

La RecycleElementAndDataTemplate strategia di memorizzazione nella cache si basa sulla RecycleElement strategia di memorizzazione nella cache assicurando inoltre che quando un ListView oggetto usa per DataTemplateSelector selezionare un DataTemplateoggetto , DataTemplate gli oggetti vengono memorizzati nella cache in base al tipo di elemento nell'elenco. Pertanto, DataTemplate gli oggetti vengono selezionati una volta per ogni tipo di elemento, anziché una volta per ogni istanza dell'elemento.

Nota

La RecycleElementAndDataTemplate strategia di memorizzazione nella cache richiede che DataTemplate gli oggetti restituiti da DataTemplateSelector devono usare il DataTemplate costruttore che accetta un oggetto Type.

Impostare la strategia di memorizzazione nella cache

La strategia di ListView memorizzazione nella cache può essere definita da in XAML impostando l'attributo CachingStrategy :

<ListView CachingStrategy="RecycleElement">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
              ...
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

In C# la strategia di memorizzazione nella cache viene impostata tramite un overload del costruttore:

ListView listView = new ListView(ListViewCachingStrategy.RecycleElement);

Impostare la strategia di memorizzazione nella cache in un controllo ListView sottoclassato

L'impostazione dell'attributo CachingStrategy da XAML in una sottoclassata ListView non produrrà il comportamento desiderato, perché non esiste alcuna CachingStrategy proprietà in ListView. La soluzione a questo problema consiste nel specificare un costruttore nella sottoclassata ListView che accetta un ListViewCachingStrategy parametro e lo passa alla classe base:

public class CustomListView : ListView
{
    public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
    {
    }
    ...
}

È quindi possibile specificare il ListViewCachingStrategy valore di enumerazione da XAML usando l'attributo x:Arguments :

<local:CustomListView>
    <x:Arguments>
        <ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
    </x:Arguments>
</local:CustomListView>

Intestazioni e piè di pagina

ListView può presentare un'intestazione e un piè di pagina che scorrono con gli elementi nell'elenco. L'intestazione e il piè di pagina possono essere stringhe, viste o DataTemplate oggetti.

ListView definisce le proprietà seguenti per specificare l'intestazione e il piè di pagina:

  • Header, di tipo object, specifica la stringa, l'associazione o la vista che verrà visualizzata all'inizio dell'elenco.
  • HeaderTemplate, di tipo DataTemplate, specifica l'oggetto DataTemplate da utilizzare per formattare l'oggetto Header.
  • Footer, di tipo object, specifica la stringa, l'associazione o la vista che verrà visualizzata alla fine dell'elenco.
  • FooterTemplate, di tipo DataTemplate, specifica l'oggetto DataTemplate da utilizzare per formattare l'oggetto Footer.

Queste proprietà sono supportate da BindableProperty oggetti , il che significa che le proprietà possono essere destinazioni di data binding.

Le Header proprietà e Footer possono essere impostate su string valori, come illustrato nell'esempio seguente:

<ListView ItemsSource="{Binding Monkeys}"
          Header="Monkeys"
          Footer="2022">
    ...
</ListView>

Lo screenshot seguente mostra l'intestazione risultante:

Screenshot of a ListView string header.

Le Header proprietà e Footer possono essere impostate su una visualizzazione. Può trattarsi di una singola visualizzazione o di una visualizzazione che contiene più visualizzazioni figlio. Nell'esempio seguente vengono illustrate le Header proprietà e Footer ognuna di esse impostata su un StackLayout oggetto che contiene un Label oggetto :

<ListView ItemsSource="{Binding Monkeys}">
    <ListView.Header>
        <StackLayout BackgroundColor="LightGray">
            <Label Margin="10,0,0,0"
                   Text="Monkeys"
                   FontSize="12"
                   FontAttributes="Bold" />
        </StackLayout>
    </ListView.Header>
    <ListView.Footer>
        <StackLayout BackgroundColor="LightGray">
            <Label Margin="10,0,0,0"
                   Text="Friends of Monkey"
                   FontSize="12"
                   FontAttributes="Bold" />
        </StackLayout>
    </ListView.Footer>
    ...
</ListView>

Lo screenshot seguente mostra l'intestazione risultante:

Screenshot of CollectionView header and footer using views.

Le HeaderTemplate proprietà e FooterTemplate possono essere impostate su DataTemplate oggetti utilizzati per formattare l'intestazione e il piè di pagina. In questo scenario, le Header proprietà e Footer devono essere associate all'origine corrente per applicare i modelli, come illustrato nell'esempio seguente:

<ListView ItemsSource="{Binding Monkeys}"
          Header="{Binding .}"
          Footer="{Binding .}">
    <ListView.HeaderTemplate>
        <DataTemplate>
            <StackLayout BackgroundColor="LightGray">
                <Label Margin="10,0,0,0"
                       Text="Monkeys"
                       FontSize="12"
                       FontAttributes="Bold" />
            </StackLayout>
        </DataTemplate>
    </ListView.HeaderTemplate>
    <ListView.FooterTemplate>
        <DataTemplate>
            <StackLayout BackgroundColor="LightGray">
                <Label Margin="10,0,0,0"
                       Text="Friends of Monkey"
                       FontSize="12"
                       FontAttributes="Bold" />
            </StackLayout>
        </DataTemplate>
    </ListView.FooterTemplate>
    ...
</ListView>

Separatori degli elementi di controllo

Per impostazione predefinita, i separatori vengono visualizzati tra ListView gli elementi in iOS e Android. Questo comportamento può essere modificato impostando la SeparatorVisibility proprietà , di tipo SeparatorVisibility, su None:

<ListView ...
          SeparatorVisibility="None" />

Inoltre, quando il separatore è abilitato, è possibile impostare il colore con la SeparatorColor proprietà :

<ListView ...
          SeparatorColor="Blue" />

Dimensioni elementi

Per impostazione predefinita, tutti gli elementi di un oggetto ListView hanno la stessa altezza, che deriva dal contenuto di DataTemplate che definisce l'aspetto di ogni elemento. Tuttavia, questo comportamento può essere modificato con le HasUnevenRows proprietà e RowHeight . Per impostazione predefinita, la HasUnevenRows proprietà è false.

La RowHeight proprietà può essere impostata su un oggetto int che rappresenta l'altezza di ogni elemento nell'oggetto ListView, a condizione che HasUnevenRows sia false. Quando HasUnevenRows è impostato su true, ogni elemento in ListView può avere un'altezza diversa. L'altezza di ogni elemento verrà derivata dal contenuto dell'elemento DataTemplatee quindi ogni elemento verrà ridimensionato in base al relativo contenuto.

I singoli ListView elementi possono essere ridimensionati a livello di codice in fase di esecuzione modificando le proprietà correlate al layout degli elementi all'interno di DataTemplate, purché la HasUnevenRows proprietà sia true. Nell'esempio seguente viene modificata l'altezza di un Image oggetto quando viene toccata:

void OnImageTapped(object sender, EventArgs args)
{
    Image image = sender as Image;
    ViewCell viewCell = image.Parent.Parent as ViewCell;

    if (image.HeightRequest < 250)
    {
      image.HeightRequest = image.Height + 100;
      viewCell.ForceUpdateSize();
    }
}

In questo esempio, il OnImageTapped gestore eventi viene eseguito in risposta a un Image oggetto che viene toccato. Il gestore eventi aggiorna l'altezza di Image e il Cell.ForceUpdateSize metodo aggiorna le dimensioni della cella, anche quando non è attualmente visibile.

Avviso

L'uso eccessivo del dimensionamento di elementi dinamici può causare ListView un peggioramento delle prestazioni.

Layout da destra a sinistra

ListView può eseguire il layout del contenuto in una direzione del flusso da destra a sinistra impostandone la FlowDirection proprietà su RightToLeft. Tuttavia, la FlowDirection proprietà deve essere impostata idealmente in un layout di pagina o radice, causando la risposta di tutti gli elementi all'interno della pagina o del layout radice alla direzione del flusso:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ListViewDemos.RightToLeftListPage"
             Title="Right to left list"
             FlowDirection="RightToLeft">
    <StackLayout Margin="20">
        <ListView ItemsSource="{Binding Monkeys}">
            ...
        </ListView>
    </StackLayout>
</ContentPage>

Il valore predefinito FlowDirection per un elemento con un elemento padre è MatchParent. Pertanto, ListView eredita il valore della FlowDirection proprietà da StackLayout, che a sua volta eredita il valore della FlowDirectionContentPageproprietà da .

Visualizzare i dati raggruppati

I set di dati di grandi dimensioni possono spesso diventare difficili quando vengono presentati in un elenco a scorrimento continuo. In questo scenario, l'organizzazione dei dati in gruppi può migliorare l'esperienza utente semplificando l'esplorazione dei dati.

I dati devono essere raggruppati prima di poter essere visualizzati. A tale scopo, è possibile creare un elenco di gruppi, in cui ogni gruppo è un elenco di elementi. L'elenco dei gruppi deve essere una IEnumerable<T> raccolta, in cui T definisce due parti di dati:

  • Nome del gruppo.
  • Raccolta IEnumerable che definisce gli elementi appartenenti al gruppo.

Il processo di raggruppamento dei dati è quindi:

  • Creare un tipo che modella un singolo elemento.
  • Creare un tipo che modella un singolo gruppo di elementi.
  • Creare una IEnumerable<T> raccolta, dove T è il tipo che modella un singolo gruppo di elementi. Questa raccolta è una raccolta di gruppi che archivia i dati raggruppati.
  • Aggiungere dati alla IEnumerable<T> raccolta.

Esempio

Quando si raggruppano i dati, il primo passaggio consiste nel creare un tipo che modella un singolo elemento. L'esempio seguente illustra la Animal classe :

public class Animal
{
    public string Name { get; set; }
    public string Location { get; set; }
    public string Details { get; set; }
    public string ImageUrl { get; set; }
}

La Animal classe modella un singolo elemento. È quindi possibile creare un tipo che modella un gruppo di elementi. L'esempio seguente illustra la AnimalGroup classe :

public class AnimalGroup : List<Animal>
{
    public string Name { get; private set; }

    public AnimalGroup(string name, List<Animal> animals) : base(animals)
    {
        Name = name;
    }
}

La AnimalGroup classe eredita dalla List<T> classe e aggiunge una Name proprietà che rappresenta il nome del gruppo.

È quindi possibile creare una IEnumerable<T> raccolta di gruppi:

public List<AnimalGroup> Animals { get; private set; } = new List<AnimalGroup>();

Questo codice definisce una raccolta denominata Animals, in cui ogni elemento dell'insieme è un AnimalGroup oggetto . Ogni AnimalGroup oggetto comprende un nome e una List<Animal> raccolta che definisce gli Animal oggetti nel gruppo.

I dati raggruppati possono quindi essere aggiunti alla Animals raccolta:

Animals.Add(new AnimalGroup("Bears", new List<Animal>
{
    new Animal
    {
        Name = "American Black Bear",
        Location = "North America",
        Details = "Details about the bear go here.",
        ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/0/08/01_Schwarzbär.jpg"
    },
    new Animal
    {
        Name = "Asian Black Bear",
        Location = "Asia",
        Details = "Details about the bear go here.",
        ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG/180px-Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG"
    },
    // ...
}));

Animals.Add(new AnimalGroup("Monkeys", new List<Animal>
{
    new Animal
    {
        Name = "Baboon",
        Location = "Africa & Asia",
        Details = "Details about the monkey go here.",
        ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
    },
    new Animal
    {
        Name = "Capuchin Monkey",
        Location = "Central & South America",
        Details = "Details about the monkey go here.",
        ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Capuchin_Costa_Rica.jpg/200px-Capuchin_Costa_Rica.jpg"
    },
    new Animal
    {
        Name = "Blue Monkey",
        Location = "Central and East Africa",
        Details = "Details about the monkey go here.",
        ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/BlueMonkey.jpg/220px-BlueMonkey.jpg"
    },
    // ...
}));

Questo codice crea due gruppi nella Animals raccolta. Il primo AnimalGroup è denominato Bearse contiene una List<Animal> raccolta di dettagli dell'orso. Il secondo AnimalGroup è denominato Monkeyse contiene una List<Animal> raccolta di dettagli della scimmia.

ListView visualizzerà i dati raggruppati, purché i dati siano stati raggruppati correttamente, impostando la IsGroupingEnabled proprietà su true:

<ListView ItemsSource="{Binding Animals}"
          IsGroupingEnabled="True">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid Padding="10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Image Grid.RowSpan="2"
                           Source="{Binding ImageUrl}"
                           Aspect="AspectFill"
                           HeightRequest="60"
                           WidthRequest="60" />
                    <Label Grid.Column="1"
                           Text="{Binding Name}"
                           FontAttributes="Bold" />
                    <Label Grid.Row="1"
                           Grid.Column="1"
                           Text="{Binding Location}"
                           FontAttributes="Italic"
                           VerticalOptions="End" />
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Il codice C# equivalente è il seguente:

ListView listView = new ListView
{
    IsGroupingEnabled = true
};
listView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
// ...

L'aspetto di ogni elemento in ListView è definito impostando la relativa ItemTemplate proprietà su un oggetto DataTemplate. Per altre informazioni, vedere Definire l'aspetto dell'elemento.

Lo screenshot seguente mostra i ListView dati raggruppati visualizzati:

Screenshot of grouped data in a ListView.

Nota

Per impostazione predefinita, ListView visualizzerà il nome del gruppo nell'intestazione del gruppo. Questo comportamento può essere modificato personalizzando l'intestazione del gruppo.

Personalizzare l'intestazione del gruppo

L'aspetto di ogni intestazione di gruppo può essere personalizzato impostando la ListView.GroupHeaderTemplate proprietà su :DataTemplate

<ListView ItemsSource="{Binding Animals}"
          IsGroupingEnabled="True">
    <ListView.GroupHeaderTemplate>
        <DataTemplate>
            <ViewCell>
                <Label Text="{Binding Name}"
                       BackgroundColor="LightGray"
                       FontSize="18"
                       FontAttributes="Bold" />
            </ViewCell>
        </DataTemplate>
    </ListView.GroupHeaderTemplate>
    ...
</ListView>

In questo esempio, ogni intestazione di gruppo è impostata su un Label oggetto che visualizza il nome del gruppo e con altre proprietà di aspetto impostate. Lo screenshot seguente mostra l'intestazione del gruppo personalizzata:

Screenshot of a customized group header in a ListView.

Importante

La GroupHeaderTemplate proprietà si escludono a vicenda con la GroupDisplayBinding proprietà . Pertanto, entrambe le proprietà non devono essere impostate.

Raggruppare senza modelli

ListViewpuò visualizzare correttamente i dati raggruppati senza impostare la ItemTemplate proprietà su :DataTemplate

<ListView ItemsSource="{Binding Animals}"
          IsGroupingEnabled="true" />

In questo scenario è possibile visualizzare dati significativi eseguendo l'override del ToString metodo nel tipo che modella un singolo elemento e il tipo che modella un singolo gruppo di elementi.

Scorrimento dei controlli

ListView definisce due ScrollTo metodi, che scorrono gli elementi nella visualizzazione. Uno degli overload scorre l'elemento specificato nella visualizzazione, mentre l'altro scorre l'elemento specificato nel gruppo specificato nella visualizzazione. Entrambi gli overload hanno argomenti aggiuntivi che consentono di specificare la posizione esatta dell'elemento dopo il completamento dello scorrimento e se animare lo scorrimento.

ListView definisce un ScrollToRequested evento generato quando viene richiamato uno dei ScrollTo metodi. L'oggetto ScrollToRequestedEventArgs che accompagna l'evento ScrollToRequested ha molte proprietà, tra cui ShouldAnimate, ModeElement, e Position. Alcune di queste proprietà vengono impostate dagli argomenti specificati nelle chiamate al ScrollTo metodo.

Definisce inoltre ListView un Scrolled evento generato per indicare che si è verificato lo scorrimento. L'oggetto ScrolledEventArgs che accompagna l'evento Scrolled ha ScrollX proprietà e ScrollY .

Rilevare lo scorrimento

ListView definisce un Scrolled evento generato per indicare che si è verificato lo scorrimento. La ItemsViewScrolledEventArgs classe , che rappresenta l'oggetto che accompagna l'evento Scrolled , definisce le proprietà seguenti:

  • ScrollX, di tipo double, rappresenta la posizione X dello scorrimento
  • ScrollY, di tipo double, rappresenta la posizione Y dello scorrimento.

L'esempio XAML seguente mostra un ListView oggetto che imposta un gestore eventi per l'evento Scrolled :

<ListView Scrolled="OnListViewScrolled">
    ...
</ListView>

Il codice C# equivalente è il seguente:

ListView listView = new ListView();
listView.Scrolled += OnListViewScrolled;

In questo esempio di codice, il OnListViewScrolled gestore eventi viene eseguito quando viene generato l'evento Scrolled :

void OnListViewScrolled(object sender, ScrolledEventArgs e)
{
    // Custom logic
}

Importante

L'evento Scrolled viene generato per gli scorrimenti avviati dall'utente e per gli scorrimenti a livello di codice.

Scorrere un elemento nella visualizzazione

Il ScrollTo metodo scorre l'elemento specificato nella visualizzazione. Dato un ListView oggetto denominato listView, l'esempio seguente mostra come scorrere l'elemento Proboscis Monkey nella visualizzazione:

MonkeysViewModel viewModel = BindingContext as MonkeysViewModel;
Monkey monkey = viewModel.Monkeys.FirstOrDefault(m => m.Name == "Proboscis Monkey");
listView.ScrollTo(monkey, ScrollToPosition.MakeVisible, true);

In alternativa, è possibile scorrere un elemento in dati raggruppati nella visualizzazione specificando l'elemento e il gruppo. L'esempio seguente mostra come scorrere l'elemento Scimmia Proboscis nel gruppo Monkeys in visualizzazione:

GroupedAnimalsViewModel viewModel = BindingContext as GroupedAnimalsViewModel;
AnimalGroup group = viewModel.Animals.FirstOrDefault(a => a.Name == "Monkeys");
Animal monkey = group.FirstOrDefault(m => m.Name == "Proboscis Monkey");
listView.ScrollTo(monkey, group, ScrollToPosition.MakeVisible, true);

Nota

L'evento ScrollToRequested viene generato quando viene richiamato il ScrollTo metodo .

Disabilitare l'animazione di scorrimento

Quando si scorre un elemento nella visualizzazione, viene visualizzata un'animazione di scorrimento. Tuttavia, questa animazione può essere disabilitata impostando l'argomento animated del ScrollTo metodo su false:

listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: false);

Posizione di scorrimento del controllo

Quando si scorre un elemento nella visualizzazione, è possibile specificare la posizione esatta dell'elemento dopo il completamento dello scorrimento con l'argomento position dei ScrollTo metodi . Questo argomento accetta un ScrollToPosition membro di enumerazione.

MakeVisible

Il ScrollToPosition.MakeVisible membro indica che l'elemento deve essere scorrevole fino a quando non è visibile nella visualizzazione:

listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: true);

Inizio

Il ScrollToPosition.Start membro indica che l'elemento deve essere scorrevole fino all'inizio della visualizzazione:

listView.ScrollTo(monkey, position: ScrollToPosition.Start, animate: true);

Center

Il ScrollToPosition.Center membro indica che l'elemento deve essere scorrevole fino al centro della visualizzazione:

listView.ScrollTo(monkey, position: ScrollToPosition.Center, animate: true);

Fine

Il ScrollToPosition.End membro indica che l'elemento deve essere scorrevole fino alla fine della visualizzazione:

listView.ScrollTo(monkey, position: ScrollToPosition.End, animate: true);

Visibilità barra di scorrimento

ListView definisce HorizontalScrollBarVisibility le proprietà e VerticalScrollBarVisibility supportate dalle proprietà associabili. Queste proprietà ottengono o impostano un ScrollBarVisibility valore di enumerazione che rappresenta quando la barra di scorrimento orizzontale o verticale è visibile. L'enumerazione ScrollBarVisibility definisce i membri seguenti:

  • Default indica il comportamento predefinito della barra di scorrimento per la piattaforma ed è il valore predefinito per le HorizontalScrollBarVisibility proprietà e VerticalScrollBarVisibility .
  • Always indica che le barre di scorrimento saranno visibili, anche quando il contenuto rientra nella visualizzazione.
  • Never indica che le barre di scorrimento non saranno visibili, anche se il contenuto non rientra nella visualizzazione.

Aggiungere menu di scelta rapida

ListView supporta gli elementi dei menu di scelta rapida, definiti come MenuItem oggetti aggiunti all'insieme ViewCell.ContextActions in DataTemplate per ogni elemento:

<ListView x:Name="listView"
          ItemsSource="{Binding Monkeys}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <ViewCell.ContextActions>
                    <MenuItem Text="Favorite"
                              Command="{Binding Source={x:Reference listView}, Path=BindingContext.FavoriteCommand}"
                              CommandParameter="{Binding}" />
                    <MenuItem Text="Delete"
                              Command="{Binding Source={x:Reference listView}, Path=BindingContext.DeleteCommand}"
                              CommandParameter="{Binding}" />
                </ViewCell.ContextActions>

                ...
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Gli MenuItem oggetti vengono visualizzati quando si fa clic con il pulsante destro del ListView mouse su un elemento in :

Screenshot of CollectionView context menu items.

Per altre informazioni sulle voci di menu, vedere Visualizzare le voci di menu.

Funzionalità Trascina verso il basso

ListView supporta la funzionalità pull per l'aggiornamento, che consente di aggiornare i dati visualizzati trascinando verso il basso nell'elenco di elementi.

Per abilitare l'aggiornamento tramite pull, impostare la IsPullToRefreshEnabled proprietà su true. Quando viene attivato un aggiornamento, ListView genera l'evento Refreshing e la IsRefreshing proprietà verrà impostata su true. Il codice necessario per aggiornare il contenuto di ListView deve quindi essere eseguito dal gestore per l'evento Refreshing o dall'implementazione eseguita dall'oggetto ICommandRefreshCommand . Dopo l'aggiornamento ListView di , la IsRefreshing proprietà deve essere impostata su falseo il EndRefresh metodo deve essere chiamato in ListViewper indicare che l'aggiornamento è stato completato.

Nell'esempio seguente viene illustrato un ListView oggetto che usa il pull per l'aggiornamento:

<ListView ItemsSource="{Binding Animals}"
          IsPullToRefreshEnabled="true"
          RefreshCommand="{Binding RefreshCommand}"
          IsRefreshing="{Binding IsRefreshing}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                ...
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

In questo esempio, quando l'utente avvia un aggiornamento, viene eseguito l'oggetto ICommand definito dalla RefreshCommand proprietà , che deve aggiornare gli elementi visualizzati. Viene visualizzata una visualizzazione di aggiornamento mentre si verifica l'aggiornamento, costituito da un cerchio di stato animato. Il valore della IsRefreshing proprietà indica lo stato corrente dell'operazione di aggiornamento. Quando viene attivato un aggiornamento, questa proprietà passerà automaticamente a true. Al termine dell'aggiornamento, è necessario reimpostare la proprietà su false.