ListView
Interfejs użytkownika aplikacji wieloplatformowej platformy .NET (.NET MAUI) ListView wyświetla przewijaną pionową listę wybranych elementów danych. Chociaż ListView zarządza wyglądem listy, wygląd każdego elementu na liście jest definiowany przez element DataTemplate , który używa elementu Cell do wyświetlania elementów. Program .NET MAUI zawiera typy komórek do wyświetlania kombinacji tekstu i obrazów, a także można zdefiniować komórki niestandardowe, które wyświetlają dowolną zawartość. ListView Obejmuje również obsługę wyświetlania nagłówków i stopek, grupowanych danych, ściągania do odświeżania i elementów menu kontekstowego.
Klasa ListView pochodzi z ItemsView<Cell>
klasy, z której dziedziczy następujące właściwości:
ItemsSource
, typuIEnumerable
, określa kolekcję elementów do wyświetlenia i ma wartośćnull
domyślną .ItemTemplate
, typu DataTemplate, określa szablon do zastosowania do każdego elementu w kolekcji elementów do wyświetlenia.
ListView definiuje następujące właściwości:
Footer
, typuobject
, określa ciąg lub widok, który będzie wyświetlany na końcu listy.FooterTemplate
, typu DataTemplate, określa DataTemplate , aby użyć do formatowaniaFooter
.GroupHeaderTemplate
, typu DataTemplate, definiuje DataTemplate używany do definiowania wyglądu nagłówka każdej grupy. Ta właściwość wzajemnie wyklucza się z właściwościąGroupDisplayBinding
. W związku z tym ustawienie tej właściwości spowoduje ustawienie wartościGroupDisplayBinding
null
.HasUnevenRows
, typubool
, wskazuje, czy elementy na liście mogą mieć wiersze o różnych wysokościach. Wartość domyślna tej właściwości tofalse
.Header
, typuobject
, określa ciąg lub widok, który będzie wyświetlany na początku listy.HeaderTemplate
, typu DataTemplate, określa DataTemplate , aby użyć do formatowaniaHeader
.HorizontalScrollBarVisibility
, typuScrollBarVisibility
, wskazuje, kiedy poziomy pasek przewijania będzie widoczny.IsGroupingEnabled
, typubool
, wskazuje, czy dane bazowe powinny być wyświetlane w grupach. Wartość domyślna tej właściwości tofalse
.IsPullToRefreshEnabled
, typubool
, wskazuje, czy użytkownik może przesunąć palcem w dół, aby spowodować ListView odświeżenie danych. Wartość domyślna tej właściwości tofalse
.IsRefreshing
, typubool
, wskazuje, czy ListView aktualnie odświeżane. Wartość domyślna tej właściwości tofalse
.RefreshCommand
, typu ICommand, reprezentuje polecenie, które zostanie wykonane po wyzwoleniu odświeżania.RefreshControlColor
, typu Color, określa kolor wizualizacji odświeżania wyświetlanej podczas odświeżania.RowHeight
, typuint
, określa wysokość każdego wiersza, gdyHasUnevenRows
ma wartośćfalse
.SelectedItem
, typuobject
, reprezentuje aktualnie wybrany element w elemencie ListView.SelectionMode
, typuListViewSelectionMode
, wskazuje, czy elementy można wybrać w ListView obiekcie , czy nie. Wartość domyślna tej właściwości toSingle
.SeparatorColor
, typu Color, definiuje kolor paska, który oddziela elementy na liście.SeparatorVisibility
, typuSeparatorVisibility
, określa, czy separatory są widoczne między elementami.VerticalScrollBarVisibility
, typuScrollBarVisibility
, wskazuje, kiedy pionowy pasek przewijania będzie widoczny.
Wszystkie te właściwości są wspierane przez BindableProperty obiekty, co oznacza, że mogą być obiektami docelowymi powiązań danych i stylizowanymi.
Ponadto ListView definiuje następujące właściwości, które nie są wspierane przez BindableProperty obiekty:
GroupDisplayBinding
, typuBindingBase
, powiązanie, które ma być używane do wyświetlania nagłówka grupy. Ta właściwość wzajemnie wyklucza się z właściwościąGroupHeaderTemplate
. W związku z tym ustawienie tej właściwości spowoduje ustawienie wartościGroupHeaderTemplate
null
.GroupShortNameBinding
, typuBindingBase
, powiązanie nazwy do wyświetlenia na pogrupowanych listach skoków.CachingStrategy
, typuListViewCachingStrategy
, definiuje strategię ponownego użycia komórek w obiekcie ListView. Jest to właściwość tylko do odczytu.
ListView definiuje następujące zdarzenia:
ItemAppearing
, który jest wywoływany po dodaniu wizualnej reprezentacji elementu do układu wizualnego elementu ListView. ObiektItemVisibilityEventArgs
, który towarzyszy temu zdarzeniu, definiujeItem
iIndex
właściwości.ItemDisappearing
, który jest zgłaszany, gdy wizualna reprezentacja elementu jest usuwana z układu wizualnego elementu ListView. ObiektItemVisibilityEventArgs
, który towarzyszy temu zdarzeniu, definiujeItem
iIndex
właściwości.ItemSelected
, który jest zgłaszany po wybraniu nowego elementu na liście. ObiektSelectedItemChangedEventArgs
, który towarzyszy temu zdarzeniu, definiujeSelectedItem
iSelectedItemIndex
właściwości.ItemTapped
, który został zgłoszony, gdy element w obiekcie ListView jest naciśnięty. ObiektItemTappedEventArgs
, który towarzyszy temu zdarzeniu, definiujeGroup
właściwości ,Item
iItemIndex
.Refreshing
, który jest wywoływany, gdy operacja ściągania do odświeżania jest wyzwalana na .ListViewScrolled
, . ObiektScrolledEventArgs
, który towarzyszy temu zdarzeniu, definiujeScrollX
iScrollY
właściwości.ScrollToRequested
. ObiektScrollToRequestedEventArgs
, który towarzyszy temu zdarzeniu, definiuje Elementwłaściwości , ,Mode
Position
,ScrollX
,ScrollY
iShouldAnimate
.
Wypełnianie obiektu ListView danymi
Element jest ListView wypełniany danymi, ustawiając jego ItemsSource
właściwość na dowolną kolekcję, która implementuje IEnumerable
element .
Ważne
ListView Jeśli element jest wymagany do odświeżenia w miarę dodawania, usuwania lub zmieniania elementów w kolekcji źródłowej, podstawowa kolekcja powinna być kolekcjąIEnumerable
, która wysyła powiadomienia o zmianie właściwości, takie jak ObservableCollection
.
ListView Można wypełnić danymi za pomocą powiązania danych, aby powiązać jego ItemsSource
właściwość z kolekcją IEnumerable
. W języku XAML jest to osiągane za Binding
pomocą rozszerzenia znaczników:
<ListView ItemsSource="{Binding Monkeys}" />
Równoważny kod języka C# to:
ListView listView = new ListView();
listView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
W tym przykładzie ItemsSource
dane właściwości są powiązane z właściwością Monkeys
połączonego modelu widoków.
Uwaga
Skompilowane powiązania można włączyć, aby zwiększyć wydajność powiązań danych w aplikacjach MAUI platformy .NET. Aby uzyskać więcej informacji, zobacz Skompilowane powiązania.
Aby uzyskać więcej informacji na temat powiązania danych, zobacz Powiązanie danych.
Definiowanie wyglądu elementu
Wygląd każdego elementu w obiekcie ListView można zdefiniować, ustawiając ItemTemplate
właściwość na wartość 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>
Elementy określone w definicji DataTemplate wyglądu każdego elementu na liście, a element podrzędny obiektu DataTemplate musi być obiektem Cell . W tym przykładzie układ w obiekcie DataTemplate jest zarządzany przez element Grid. Obiekt Grid zawiera Image obiekt i dwa Label obiekty, które są powiązane z właściwościami Monkey
klasy:
public class Monkey
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
Poniższy zrzut ekranu przedstawia wynik tworzenia szablonów dla każdego elementu na liście:
Aby uzyskać więcej informacji na temat szablonów danych, zobacz Szablony danych.
Cells
Wygląd każdego elementu w obiekcie ListView jest definiowany przez DataTemplateelement , a DataTemplate element musi odwoływać się Cell do klasy, aby wyświetlić elementy. Każda komórka reprezentuje element danych w obiekcie ListView. Program .NET MAUI zawiera następujące wbudowane komórki:
- TextCell, który wyświetla tekst podstawowy i pomocniczy w oddzielnych wierszach.
- ImageCell, który wyświetla obraz z tekstem podstawowym i pomocniczym w osobnych wierszach.
- SwitchCell, który wyświetla tekst i przełącznik, który można włączyć lub wyłączyć.
- EntryCell, który wyświetla etykietę i tekst, który można edytować.
- ViewCell, która jest komórką niestandardową, której wygląd jest definiowany Viewprzez element . Ten typ komórki powinien być używany, gdy chcesz w pełni zdefiniować wygląd każdego elementu w elemencie ListView.
SwitchCell Zazwyczaj i EntryCell będzie używany tylko w obiekcie TableView i nie będzie używany w obiekcie ListView. Aby uzyskać więcej informacji na temat SwitchCell elementów i EntryCell, zobacz TableView.
Komórka tekstowa
Element wyświetla TextCell tekst podstawowy i pomocniczy w oddzielnych wierszach. TextCell definiuje następujące właściwości:
Text
, typustring
, definiuje tekst podstawowy do wyświetlenia.TextColor
, typu Color, reprezentuje kolor tekstu podstawowego.Detail
, typustring
, definiuje tekst pomocniczy do wyświetlenia.DetailColor
, typu Color, wskazuje kolor tekstu pomocniczego.Command
, typu ICommand, definiuje polecenie, które jest wykonywane, gdy komórka jest naciśnięta.CommandParameter
, typuobject
, reprezentuje parametr przekazany do polecenia.
Te właściwości są wspierane przez BindableProperty obiekty, co oznacza, że mogą być obiektami docelowymi powiązań danych i stylizowanymi.
W poniższym przykładzie pokazano użycie elementu w celu TextCell zdefiniowania wyglądu elementów w obiekcie ListView:
<ListView ItemsSource="{Binding Food}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}"
Detail="{Binding Description}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Poniższy zrzut ekranu przedstawia wynikowy wygląd komórki:
Komórka obrazu
Obiekt ImageCell wyświetla obraz z tekstem podstawowym i pomocniczym w oddzielnych wierszach. ImageCell dziedziczy właściwości z TextCell, i definiuje ImageSource właściwość typu ImageSource, który określa obraz do wyświetlenia w komórce. Ta właściwość jest wspierana BindableProperty przez obiekt, co oznacza, że może być obiektem docelowym powiązań danych i być stylizowany.
W poniższym przykładzie pokazano użycie elementu w celu ImageCell zdefiniowania wyglądu elementów w obiekcie ListView:
<ListView ItemsSource="{Binding Food}">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell ImageSource="{Binding Image}"
Text="{Binding Name}"
Detail="{Binding Description}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Poniższy zrzut ekranu przedstawia wynikowy wygląd komórki:
Wyświetl komórkę
A ViewCell to komórka niestandardowa, której wygląd jest definiowany przez element View. ViewCellView definiuje właściwość typu View, która definiuje widok reprezentujący zawartość komórki. Ta właściwość jest wspierana BindableProperty przez obiekt, co oznacza, że może być obiektem docelowym powiązań danych i być stylizowany.
Uwaga
Właściwość View jest właściwością ViewCell content klasy i dlatego nie musi być jawnie ustawiana z języka XAML.
W poniższym przykładzie pokazano użycie elementu w celu ViewCell zdefiniowania wyglądu elementów w obiekcie ListView:
<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>
W systemie ViewCellukład może być zarządzany przez dowolny układ MAUI platformy .NET. W tym przykładzie układ jest zarządzany przez element Grid. Obiekt Grid zawiera Image obiekt i dwa Label obiekty, które są powiązane z właściwościami Monkey
klasy.
Poniższy zrzut ekranu przedstawia wynik tworzenia szablonów dla każdego elementu na liście:
Wybieranie wyglądu elementu w czasie wykonywania
Wygląd każdego elementu w ListView obiekcie można wybrać w czasie wykonywania na podstawie wartości elementu, ustawiając ItemTemplate
właściwość na DataTemplateSelector obiekt:
<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>
<Grid Margin="20">
<ListView ItemsSource="{Binding Monkeys}"
ItemTemplate="{StaticResource MonkeySelector}" />
</Grid>
</ContentPage>
Właściwość ItemTemplate
jest ustawiana na MonkeyDataTemplateSelector
obiekt. W poniższym przykładzie przedstawiono klasę MonkeyDataTemplateSelector
:
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;
}
}
Klasa MonkeyDataTemplateSelector
definiuje AmericanMonkey
właściwości, OtherMonkey
DataTemplate które są ustawione na różne szablony danych. Przesłonięcia OnSelectTemplate
zwracają AmericanMonkey
szablon, który wyświetla nazwę małpy i lokalizację w teal, gdy nazwa małpy zawiera "Ameryka". Gdy nazwa małpy nie zawiera "Ameryka", OnSelectTemplate
zastąpienie zwraca OtherMonkey
szablon, który wyświetla nazwę małpy i lokalizację w srebrze:
Aby uzyskać więcej informacji na temat selektorów szablonów danych, zobacz Create a DataTemplateSelector (Tworzenie selektora szablonów danych).
Odpowiadanie na wybór elementu
Domyślnie ListView zaznaczenie jest włączone. To zachowanie można jednak zmienić, ustawiając SelectionMode
właściwość . Wyliczenie ListViewSelectionMode
definiuje następujące elementy członkowskie:
None
— wskazuje, że nie można wybrać elementów.Single
— wskazuje, że można wybrać pojedynczy element z wyróżnionym wybranym elementem. Jest to wartość domyślna.
ListViewItemSelected
Definiuje zdarzenie, które jest zgłaszane, gdy SelectedItem
właściwość ulegnie zmianie, albo z powodu wybrania elementu z listy przez użytkownika lub gdy aplikacja ustawia właściwość. Obiekt SelectedItemChangedEventArgs
, który towarzyszy temu zdarzeniu, ma SelectedItem
właściwości i SelectedItemIndex
.
Gdy właściwość jest ustawiona SelectionMode
na , można wybrać Single
pojedynczy element w elemencie ListView . Po wybraniu SelectedItem
elementu właściwość zostanie ustawiona na wartość wybranego elementu. Gdy ta właściwość ulegnie zmianie, ItemSelected
zdarzenie zostanie zgłoszone.
W poniższym przykładzie pokazano element ListView , który może odpowiadać na wybór pojedynczego elementu:
<ListView ItemsSource="{Binding Monkeys}"
ItemSelected="OnItemSelected">
...
</ListView>
W tym przykładzie OnItemSelected
program obsługi zdarzeń jest wykonywany po uruchomieniu ItemSelected
zdarzenia, a program obsługi zdarzeń pobiera wybrany element:
void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
Monkey item = args.SelectedItem as Monkey;
}
Poniższy zrzut ekranu przedstawia wybór pojedynczego elementu w elemencie ListView:
Wyczyść zaznaczenie
Właściwość SelectedItem
można wyczyścić, ustawiając ją lub obiekt, z którą jest powiązana, na null
.
Wyłączanie zaznaczenia
ListView zaznaczenie jest domyślnie włączone. Można go jednak wyłączyć, ustawiając SelectionMode
właściwość na None
:
<ListView ...
SelectionMode="None" />
Gdy właściwość jest ustawiona SelectionMode
na , nie można wybrać None
elementów w ListView obiekcie , SelectedItem
właściwość pozostanie null
, a ItemSelected
zdarzenie nie zostanie wyzwolone.
Dane pamięci podręcznej
ListView to zaawansowany widok wyświetlania danych, ale ma pewne ograniczenia. Wydajność przewijania może mieć miejsce w przypadku używania komórek niestandardowych, zwłaszcza gdy zawierają głęboko zagnieżdżone hierarchie widoków lub używają niektórych układów wymagających złożonego pomiaru. Na szczęście istnieją techniki, których można użyć, aby uniknąć niskiej wydajności.
Element A ListView jest często używany do wyświetlania znacznie większej ilości danych niż pasuje do ekranu. Na przykład aplikacja muzyczna może mieć bibliotekę piosenek z tysiącami wpisów. Utworzenie elementu dla każdego wpisu spowoduje marnowanie cennej pamięci i słabe działanie. Tworzenie i niszczenie wierszy stale wymagałoby, aby aplikacja tworzyła wystąpienia obiektów i czyściła je stale, co również działałoby źle.
Aby zaoszczędzić pamięć, natywne ListView odpowiedniki dla każdej platformy mają wbudowane funkcje ponownego użycia wierszy. Tylko komórki widoczne na ekranie są ładowane w pamięci, a zawartość jest ładowana do istniejących komórek. Ten wzorzec uniemożliwia aplikacji utworzenie wystąpienia tysięcy obiektów, oszczędność czasu i pamięci.
Program .NET MAUI umożliwia ListView ponowne użycie komórek za pomocą ListViewCachingStrategy
wyliczenia, które definiuje następujące elementy członkowskie:
RetainElement
, określa, że ListView wygeneruje komórkę dla każdego elementu na liście.RecycleElement
, określa, że ListView próba zminimalizowania zużycia pamięci i szybkości wykonywania przez odtworzenie komórek listy.RecycleElementAndDataTemplate
, podobnie jakRecycleElement
podczas zapewniania, że w przypadku ListView użycia DataTemplate DataTemplateSelectorobiektu obiekty są buforowane przez typ elementu na liście.
Zachowaj elementy
Strategia RetainElement
buforowania określa, że ListView wygeneruje komórkę dla każdego elementu na liście i jest zachowaniem domyślnym ListView . Należy go użyć w następujących okolicznościach:
- Każda komórka ma dużą liczbę powiązań (20–30+).
- Szablon komórki często się zmienia.
- Testowanie pokazuje, że
RecycleElement
strategia buforowania powoduje zmniejszenie szybkości wykonywania.
Ważne jest, aby rozpoznać konsekwencje RetainElement
strategii buforowania podczas pracy z komórkami niestandardowymi. Każdy kod inicjowania komórek musi zostać uruchomiony dla każdego utworzenia komórki, co może być wielokrotnie na sekundę. W takiej sytuacji techniki układu, które były w porządku na stronie, takie jak używanie wielu zagnieżdżonych Grid obiektów, stają się wąskimi gardłami wydajności podczas konfigurowania i niszczenia w czasie rzeczywistym podczas przewijania użytkownika.
Elementy recyklingu
Strategia RecycleElement
buforowania określa, że ListView próba zminimalizowania zużycia pamięci i szybkości wykonywania przez odtworzenie komórek listy. Ten tryb nie zawsze oferuje poprawę wydajności, a testowanie należy wykonać w celu ustalenia wszelkich ulepszeń. Jest to jednak preferowany wybór i powinien być używany w następujących okolicznościach:
- Każda komórka ma niewielką do umiarkowaną liczbę powiązań.
- Każda
BindingContext
komórka definiuje wszystkie dane komórek. - Każda komórka jest w dużej mierze podobna, a szablon komórki jest niezmienny.
Podczas wirtualizacji komórka będzie miała zaktualizowany kontekst powiązania, a więc jeśli aplikacja korzysta z tego trybu, musi upewnić się, że aktualizacje kontekstu powiązania są odpowiednio obsługiwane. Mogą wystąpić wszystkie dane dotyczące komórki z kontekstu powiązania lub błędy spójności. Ten problem można uniknąć, używając powiązania danych do wyświetlania danych komórek. Alternatywnie dane komórek powinny być ustawiane w przesłonięć OnBindingContextChanged
, a nie w konstruktorze komórki niestandardowej, jak pokazano w poniższym przykładzie:
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;
}
}
}
Odtwarzanie elementów za pomocą elementu DataTemplateSelector
Jeśli element ListView używa DataTemplateSelector elementu do wybrania DataTemplateelementu , RecycleElement
strategia buforowania nie buforuje DataTemplate obiektów. Zamiast tego element DataTemplate jest wybierany dla każdego elementu danych na liście.
Uwaga
Strategia RecycleElement
buforowania wymaga, aby po DataTemplateSelector wyświetleniu monitu DataTemplate o wybranie elementu każdy DataTemplate musi zwrócić ten sam ViewCell typ. Na przykład w przypadku ListView elementu z wartością DataTemplateSelector , która może zwrócić wartość MyDataTemplateA
(gdzie MyDataTemplateA
zwraca ViewCell typ MyViewCellA
), lub MyDataTemplateB
(gdzie MyDataTemplateB
zwraca ViewCell MyViewCellB
typ ), gdy MyDataTemplateA
jest zwracana wartość musi zostać zwrócona MyViewCellA
lub zostanie zgłoszony wyjątek.
Odtwarzanie elementów za pomocą elementów DataTemplates
Strategia RecycleElementAndDataTemplate
buforowania opiera się na RecycleElement
strategii buforowania, dodatkowo upewniając się, że w przypadku ListView DataTemplateSelector wybrania obiektu w DataTemplate celu wybrania DataTemplateobiektu obiekty są buforowane według typu elementu na liście. DataTemplate W związku z tym obiekty są wybierane raz na typ elementu, a nie raz na wystąpienie elementu.
Uwaga
Strategia RecycleElementAndDataTemplate
buforowania wymaga, aby DataTemplate obiekty zwracane przez DataTemplateSelector obiekt musi używać konstruktora DataTemplate , który przyjmuje Type
element .
Ustawianie strategii buforowania
Strategię ListView buforowania można zdefiniować w języku XAML, ustawiając CachingStrategy
atrybut:
<ListView CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
W języku C# strategia buforowania jest ustawiana za pośrednictwem przeciążenia konstruktora:
ListView listView = new ListView(ListViewCachingStrategy.RecycleElement);
Ustawianie strategii buforowania w podklasowanej klasie ListView
Ustawienie atrybutu CachingStrategy
z XAML w podklasie ListView nie spowoduje uzyskania żądanego zachowania, ponieważ nie CachingStrategy
ma właściwości na .ListView Rozwiązaniem tego problemu jest określenie konstruktora w podklasie ListView ListViewCachingStrategy
, który akceptuje parametr i przekazuje go do klasy bazowej:
public class CustomListView : ListView
{
public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
{
}
...
}
ListViewCachingStrategy
Następnie można określić wartość wyliczenia z języka XAML przy użyciu atrybutu x:Arguments
:
<local:CustomListView>
<x:Arguments>
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
</x:Arguments>
</local:CustomListView>
Nagłówki i stopki
ListView może przedstawiać nagłówek i stopkę, która przewija się z elementami na liście. Nagłówek i stopka mogą być ciągami, widokami lub DataTemplate obiektami.
ListView definiuje następujące właściwości określania nagłówka i stopki:
Header
, typuobject
, określa ciąg, powiązanie lub widok, który będzie wyświetlany na początku listy.HeaderTemplate
, typu DataTemplate, określa DataTemplate , aby użyć do formatowaniaHeader
.Footer
, typuobject
, określa ciąg, powiązanie lub widok, który będzie wyświetlany na końcu listy.FooterTemplate
, typu DataTemplate, określa DataTemplate , aby użyć do formatowaniaFooter
.
Te właściwości są wspierane przez BindableProperty obiekty, co oznacza, że właściwości mogą być obiektami docelowymi powiązań danych.
Wyświetlanie ciągów w nagłówku i stopce
Właściwości Header
i Footer
można ustawić na string
wartości, jak pokazano w poniższym przykładzie:
<ListView ItemsSource="{Binding Monkeys}"
Header="Monkeys"
Footer="2022">
...
</ListView>
Poniższy zrzut ekranu przedstawia wynikowy nagłówek:
Wyświetlanie widoków w nagłówku i stopce
Właściwości Header
i Footer
można ustawić na widok. Może to być pojedynczy widok lub widok zawierający wiele widoków podrzędnych. W poniższym przykładzie pokazano Header
właściwości i Footer
dla każdego zestawu Grid obiektów zawierającego Label obiekt:
<ListView ItemsSource="{Binding Monkeys}">
<ListView.Header>
<Grid BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="12"
FontAttributes="Bold" />
</Grid>
</ListView.Header>
<ListView.Footer>
<Grid BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Monkey"
FontSize="12"
FontAttributes="Bold" />
</Grid>
</ListView.Footer>
...
</ListView>
Poniższy zrzut ekranu przedstawia wynikowy nagłówek:
Wyświetlanie szablonu nagłówka i stopki
Właściwości HeaderTemplate
i FooterTemplate
można ustawić na DataTemplate obiekty, które są używane do formatowania nagłówka i stopki. W tym scenariuszu Header
właściwości i Footer
muszą być powiązane z bieżącym źródłem, aby szablony były stosowane, jak pokazano w poniższym przykładzie:
<ListView ItemsSource="{Binding Monkeys}"
Header="{Binding .}"
Footer="{Binding .}">
<ListView.HeaderTemplate>
<DataTemplate>
<Grid BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="12"
FontAttributes="Bold" />
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.FooterTemplate>
<DataTemplate>
<Grid BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Monkey"
FontSize="12"
FontAttributes="Bold" />
</Grid>
</DataTemplate>
</ListView.FooterTemplate>
...
</ListView>
Separatory elementów sterujących
Domyślnie separatory są wyświetlane między elementami ListView w systemach iOS i Android. To zachowanie można zmienić, ustawiając SeparatorVisibility
właściwość typu SeparatorVisibility
, na None
:
<ListView ...
SeparatorVisibility="None" />
Ponadto po włączeniu separatora można ustawić kolor za pomocą SeparatorColor
właściwości :
<ListView ...
SeparatorColor="Blue" />
Rozmiar elementów
Domyślnie wszystkie elementy w obiekcie ListView mają taką samą wysokość, która pochodzi z zawartości DataTemplate obiektu definiującego wygląd każdego elementu. To zachowanie można jednak zmienić za HasUnevenRows
pomocą właściwości i RowHeight
. Domyślnie HasUnevenRows
właściwość to false
.
Właściwość RowHeight
można ustawić na wartość reprezentującą int
wysokość każdego elementu w elemencie ListView, pod warunkiem, że HasUnevenRows
jest to false
. Gdy HasUnevenRows
jest ustawiona wartość true
, każdy element w obiekcie ListView może mieć inną wysokość. Wysokość każdego elementu będzie pochodzić z zawartości elementu DataTemplate, a więc każdy element będzie mieć rozmiar do jego zawartości.
Rozmiar poszczególnych ListView elementów można zmienić programowo w czasie wykonywania, zmieniając właściwości powiązane z układem elementów w obiekcie DataTemplate, pod warunkiem, że HasUnevenRows
właściwość ma wartość true
. Poniższy przykład zmienia wysokość obiektu po naciśnięciu Image :
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();
}
}
W tym przykładzie OnImageTapped
program obsługi zdarzeń jest wykonywany w odpowiedzi na obiekt, który jest naciśnięty Image . Procedura obsługi zdarzeń aktualizuje wysokość Image obiektu , a Cell.ForceUpdateSize
metoda aktualizuje rozmiar komórki, nawet jeśli nie jest ona obecnie widoczna.
Ostrzeżenie
Nadmierne wykorzystanie rozmiaru elementu dynamicznego może spowodować ListView obniżenie wydajności.
Układ od prawej do lewej
ListView może układać jego zawartość w kierunku przepływu od prawej do lewej, ustawiając jej FlowDirection
właściwość na RightToLeft
. FlowDirection
Jednak właściwość powinna być ustawiana na stronie lub układzie głównym, co powoduje, że wszystkie elementy w obrębie strony lub układu głównego powinny odpowiadać na kierunek przepływu:
<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">
<Grid Margin="20">
<ListView ItemsSource="{Binding Monkeys}">
...
</ListView>
</Grid>
</ContentPage>
Wartość domyślna FlowDirection
elementu z elementem nadrzędnym to MatchParent
. ListView W związku z tym właściwość dziedziczy FlowDirection
wartość właściwości z Gridklasy , która z kolei dziedziczy FlowDirection
wartość właściwości z ContentPageklasy .
Wyświetlanie pogrupowanych danych
Duże zestawy danych często stają się niewygodne podczas ciągłego przewijania listy. W tym scenariuszu organizowanie danych w grupach może poprawić środowisko użytkownika, ułatwiając nawigowanie po danych.
Dane muszą być pogrupowane, zanim będzie można je wyświetlić. Można to zrobić, tworząc listę grup, w których każda grupa jest listą elementów. Lista grup powinna być kolekcją IEnumerable<T>
, w której T
definiuje się dwa fragmenty danych:
- Nazwa grupy.
- Kolekcja
IEnumerable
definiująca elementy należące do grupy.
W związku z tym proces grupowania danych polega na:
- Utwórz typ, który modeluje pojedynczy element.
- Utwórz typ, który modeluje pojedynczą grupę elementów.
- Utwórz kolekcję, gdzie
T
jest typemIEnumerable<T>
, który modeluje pojedynczą grupę elementów. Ta kolekcja jest kolekcją grup, która przechowuje zgrupowane dane. - Dodaj dane do kolekcji
IEnumerable<T>
.
Przykład
Podczas grupowania danych pierwszym krokiem jest utworzenie typu, który modeluje pojedynczy element. W poniższym przykładzie przedstawiono klasę Animal
:
public class Animal
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
Klasa Animal
modeluje pojedynczy element. Typ, który modeluje grupę elementów, można następnie utworzyć. W poniższym przykładzie przedstawiono klasę AnimalGroup
:
public class AnimalGroup : List<Animal>
{
public string Name { get; private set; }
public AnimalGroup(string name, List<Animal> animals) : base(animals)
{
Name = name;
}
}
Klasa AnimalGroup
dziedziczy z List<T>
klasy i dodaje właściwość reprezentującą Name
nazwę grupy.
Następnie IEnumerable<T>
można utworzyć kolekcję grup:
public List<AnimalGroup> Animals { get; private set; } = new List<AnimalGroup>();
Ten kod definiuje kolekcję o nazwie Animals
, gdzie każdy element w kolekcji jest obiektem AnimalGroup
. Każdy AnimalGroup
obiekt składa się z nazwy i List<Animal>
kolekcji definiującej Animal
obiekty w grupie.
Pogrupowane dane można następnie dodać do kolekcji Animals
:
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"
},
// ...
}));
Ten kod tworzy dwie grupy w kolekcji Animals
. Pierwszy AnimalGroup
nosi nazwę Bears
i zawiera List<Animal>
kolekcję szczegółów niedźwiedzia. Drugi AnimalGroup
nosi nazwę Monkeys
i zawiera List<Animal>
kolekcję szczegółów małpy.
ListView spowoduje wyświetlenie pogrupowanych danych, pod warunkiem, że dane zostały prawidłowo zgrupowane, ustawiając IsGroupingEnabled
właściwość na 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>
Równoważny kod języka C# to:
ListView listView = new ListView
{
IsGroupingEnabled = true
};
listView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
// ...
Wygląd każdego elementu w obiekcie ListView jest definiowany przez ustawienie jego ItemTemplate
właściwości na DataTemplatewartość . Aby uzyskać więcej informacji, zobacz Definiowanie wyglądu elementu.
Poniższy zrzut ekranu przedstawia ListView wyświetlane pogrupowane dane:
Uwaga
Domyślnie ListView nazwa grupy będzie wyświetlana w nagłówku grupy. To zachowanie można zmienić, dostosowując nagłówek grupy.
Dostosowywanie nagłówka grupy
Wygląd każdego nagłówka grupy można dostosować, ustawiając ListView.GroupHeaderTemplate
właściwość na wartość 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>
W tym przykładzie każdy nagłówek grupy jest ustawiony na , Label który wyświetla nazwę grupy i ma inne właściwości wyglądu ustawione. Poniższy zrzut ekranu przedstawia dostosowany nagłówek grupy:
Ważne
Obiekt GroupHeaderTemplate
wzajemnie się wyklucza z GroupDisplayBinding
nieruchomością. W związku z tym nie należy ustawiać obu właściwości.
Grupuj bez szablonów
ListView może wyświetlać poprawnie zgrupowane dane bez ustawiania ItemTemplate
właściwości na DataTemplatewartość :
<ListView ItemsSource="{Binding Animals}"
IsGroupingEnabled="true" />
W tym scenariuszu można wyświetlić istotne dane, przesłaniając ToString
metodę w typie modelowym pojedynczego elementu oraz typ modelujący pojedynczą grupę elementów.
Przewijanie kontrolki
ListView definiuje dwie ScrollTo
metody, które przewijają elementy do widoku. Jedno z przeciążeń przewija określony element do widoku, podczas gdy drugi przewija określony element w określonej grupie do widoku. Oba przeciążenia mają dodatkowe argumenty, które umożliwiają dokładne położenie elementu po zakończeniu przewijania i czy można animować przewijania.
ListViewScrollToRequested
definiuje zdarzenie, które jest wyzwalane po wywołaniu jednej z ScrollTo
metod. Obiekt ScrollToRequestedEventArgs
, który towarzyszy ScrollToRequested
zdarzeniu ma wiele właściwości, w tym ShouldAnimate
, Element, Mode
i Position
. Niektóre z tych właściwości są ustawiane z argumentów określonych w ScrollTo
wywołaniach metody.
Ponadto definiuje Scrolled
zdarzenie, które jest wyzwalane, ListView aby wskazać, że wystąpiło przewijanie. Obiekt ScrolledEventArgs
, który towarzyszy Scrolled
zdarzeniu, ma ScrollX
właściwości i ScrollY
.
Wykrywanie przewijania
ListView definiuje zdarzenie Scrolled
, które jest wyzwalane, aby wskazać, że wystąpiło przewijanie. Klasa ItemsViewScrolledEventArgs
, która reprezentuje obiekt, który towarzyszy Scrolled
zdarzeniu, definiuje następujące właściwości:
ScrollX
, typudouble
, reprezentuje pozycję X przewijaniaScrollY
, typudouble
, reprezentuje pozycję Y przewijania.
W poniższym przykładzie XAML pokazano element ListView , który ustawia procedurę obsługi zdarzeń dla Scrolled
zdarzenia:
<ListView Scrolled="OnListViewScrolled">
...
</ListView>
Równoważny kod języka C# to:
ListView listView = new ListView();
listView.Scrolled += OnListViewScrolled;
W tym przykładzie OnListViewScrolled
kodu program obsługi zdarzeń jest wykonywany po uruchomieniu Scrolled
zdarzenia:
void OnListViewScrolled(object sender, ScrolledEventArgs e)
{
// Custom logic
}
Ważne
Zdarzenie Scrolled
jest wyzwalane dla przewijania inicjowanych przez użytkownika i przewijania programowego.
Przewijanie elementu do widoku
Metoda ScrollTo
przewija określony element do widoku. ListView Biorąc pod uwagę obiekt o nazwie listView
, w poniższym przykładzie pokazano, jak przewinąć element Proboscis Monkey do widoku:
MonkeysViewModel viewModel = BindingContext as MonkeysViewModel;
Monkey monkey = viewModel.Monkeys.FirstOrDefault(m => m.Name == "Proboscis Monkey");
listView.ScrollTo(monkey, ScrollToPosition.MakeVisible, true);
Alternatywnie element w pogrupowanych danych można przewinąć do widoku, określając element i grupę. W poniższym przykładzie pokazano, jak przewinąć element Proboscis Monkey w grupie Małpy w widoku:
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);
Uwaga
Zdarzenie ScrollToRequested
jest wyzwalane po ScrollTo
wywołaniu metody.
Wyłączanie animacji przewijania
Animacja przewijania jest wyświetlana podczas przewijania elementu do widoku. Tę animację można jednak wyłączyć, ustawiając animated
argument ScrollTo
metody na false
:
listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: false);
Położenie przewijania kontrolki
Podczas przewijania elementu do widoku można określić dokładną pozycję elementu po zakończeniu przewijania za pomocą position
argumentu ScrollTo
metod. Ten argument akceptuje element członkowski ScrollToPosition
wyliczenia.
MakeVisible
Element ScrollToPosition.MakeVisible
członkowski wskazuje, że element powinien być przewijany, dopóki nie będzie widoczny w widoku:
listView.ScrollTo(monkey, position: ScrollToPosition.MakeVisible, animate: true);
Rozpocznij
Element ScrollToPosition.Start
członkowski wskazuje, że element powinien zostać przewinięty do początku widoku:
listView.ScrollTo(monkey, position: ScrollToPosition.Start, animate: true);
Wyśrodkuj
Element ScrollToPosition.Center
członkowski wskazuje, że element powinien zostać przewinięty do środka widoku:
listView.ScrollTo(monkey, position: ScrollToPosition.Center, animate: true);
Zakończenie
Element ScrollToPosition.End
członkowski wskazuje, że element powinien zostać przewinięty na końcu widoku:
listView.ScrollTo(monkey, position: ScrollToPosition.End, animate: true);
Widoczność paska przewijania
ListView definiuje HorizontalScrollBarVisibility
i VerticalScrollBarVisibility
właściwości, które są wspierane przez właściwości możliwe do powiązania. Te właściwości pobierają lub ustawiają wartość wyliczenia reprezentującą ScrollBarVisibility
, gdy pasek przewijania poziomego lub pionowego jest widoczny. Wyliczenie ScrollBarVisibility
definiuje następujące elementy członkowskie:
Default
wskazuje domyślne zachowanie paska przewijania dla platformy i jest wartością domyślną właściwościHorizontalScrollBarVisibility
iVerticalScrollBarVisibility
.Always
wskazuje, że paski przewijania będą widoczne, nawet jeśli zawartość pasuje do widoku.Never
wskazuje, że paski przewijania nie będą widoczne, nawet jeśli zawartość nie pasuje do widoku.
Dodawanie menu kontekstowych
ListView obsługuje elementy menu kontekstowego, które są definiowane jako MenuItem obiekty dodawane do ViewCell.ContextActions
kolekcji w elemencie DataTemplate dla każdego elementu:
<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>
Obiekty MenuItem są ujawniane po kliknięciu ListView prawym przyciskiem myszy elementu:
Aby uzyskać więcej informacji na temat elementów menu, zobacz Wyświetlanie elementów menu.
Przeciągnij, aby odświeżyć
ListView obsługuje funkcję ściągania do odświeżania, która umożliwia odświeżanie danych wyświetlanych przez ściąganie na liście elementów.
Aby włączyć odświeżanie ściągania, ustaw IsPullToRefreshEnabled
właściwość na true
. Po wyzwoleniu ListView odświeżania zgłasza Refreshing
zdarzenie, a właściwość zostanie ustawiona IsRefreshing
na true
wartość . Kod wymagany do odświeżenia zawartości ListView obiektu powinien następnie zostać wykonany przez program obsługi dla Refreshing
zdarzenia lub przez implementację ICommand wykonywaną RefreshCommand
przez program obsługi. ListView Po odświeżeniu IsRefreshing
właściwości należy ustawić false
wartość , lub EndRefresh
metodę należy wywołać w ListViewobiekcie , aby wskazać, że odświeżanie zostało ukończone.
W poniższym przykładzie pokazano element , który używa ściągnięcia ListView do odświeżenia:
<ListView ItemsSource="{Binding Animals}"
IsPullToRefreshEnabled="true"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
W tym przykładzie, gdy użytkownik inicjuje odświeżanie, ICommand jest wykonywany zdefiniowany przez RefreshCommand
właściwość, co powinno odświeżyć wyświetlane elementy. Wizualizacja odświeżania jest wyświetlana podczas odświeżania, która składa się z animowanego okręgu postępu. Wartość IsRefreshing
właściwości wskazuje bieżący stan operacji odświeżania. Po wyzwoleniu odświeżania ta właściwość zostanie automatycznie przeniesiona do true
elementu . Po zakończeniu odświeżania należy zresetować właściwość do false
.