Bindbare Layouts in Xamarin.Forms
Bindungsfähige Layouts ermöglichen jede Layoutklasse, die von der Layout<T>
Klasse abgeleitet wird, um ihren Inhalt zu generieren, indem sie an eine Sammlung von Elementen gebunden wird, mit der Option zum Festlegen der Darstellung der einzelnen Elemente mit einer DataTemplate
. Bindbare Layouts werden von der BindableLayout
-Klasse bereitgestellt, die die folgenden angefügten Eigenschaften verfügbar macht:
ItemsSource
– gibt die Sammlung vonIEnumerable
-Elementen an, die vom Layout angezeigt werden sollen.ItemTemplate
– gibt dieDataTemplate
an, das auf jedes Element in der Sammlung der angezeigten Elemente angewendet werden soll.ItemTemplateSelector
– gibt denDataTemplateSelector
an, der verwendet wird, um zur Runtime eineDataTemplate
für ein Element auszuwählen.
Hinweis
Die ItemTemplate
-Eigenschaft hat Vorrang, wenn sowohl die Eigenschaft ItemTemplate
als auch die Eigenschaft ItemTemplateSelector
festgelegt wird.
Darüber hinaus macht die BindableLayout
-Klasse die folgenden bindbaren Eigenschaften verfügbar:
EmptyView
– gibt diestring
oder die Ansicht an, die angezeigt wird, wenn dieItemsSource
-Eigenschaftnull
ist, oder wenn die durch dieItemsSource
-Eigenschaft angegebene Sammlungnull
oder leer ist. Der Standardwert istnull
.EmptyViewTemplate
– gibt dieDataTemplate
-Eigenschaft an, die angezeigt wird, wenn dieItemsSource
-Eigenschaftnull
ist, oder wenn die durch dieItemsSource
-Eigenschaft angegebene Sammlungnull
oder leer ist. Der Standardwert istnull
.
Hinweis
Wenn Sie beispielsweise die Eigenschaft EmptyView
und die Eigenschaft EmptyViewTemplate
festlegen, hat die Eigenschaft EmptyViewTemplate
Vorrang.
Alle diese Eigenschaften können an die AbsoluteLayout
Klassen , FlexLayout
, Grid
, RelativeLayout
und StackLayout
klassen angefügt werden, die alle von der Layout<T>
Klasse abgeleitet sind.
Die Layout<T>
Klasse macht eine Children
Auflistung verfügbar, der die untergeordneten Elemente eines Layouts hinzugefügt werden. Wenn die BindableLayout.ItemsSource
Eigenschaft auf eine Auflistung von Elementen festgelegt und an eine Layout<T>
abgeleitete Klasse angefügt ist, wird jedes Element in der Auflistung zur Layout<T>.Children
Anzeige durch das Layout hinzugefügt. Die Layout<T>
-abgeleitete Klasse aktualisiert dann die untergeordneten Ansichten, wenn sich die zugrunde liegende Auflistung ändert. Weitere Informationen zum Xamarin.Forms Layoutzyklus finden Sie unter Erstellen eines benutzerdefinierten Layouts.
Bindende Layouts sollten nur verwendet werden, wenn die anzuzeigende Sammlung von Elementen klein ist, und kein Scrollen und Auswählen benötigt wird. Der Bildlauf kann zwar durch Umbruch eines gebundenen Layouts in einer ScrollView
bereitgestellt werden, dies wird jedoch nicht empfohlen, da bindbare Layouts keine UI-Virtualisierung aufweisen. Wenn ein Bildlauf benötigt wird, sollte eine scrollbare Ansicht verwendet werden, die UI-Virtualisierung enthält, wie ListView
oder CollectionView
, Wenn diese Empfehlung nicht beachtet wird, kann dies zu Leistungsproblemen führen.
Wichtig
Obwohl es technisch möglich ist, ein bindungsfähiges Layout an jede Layoutklasse anzufügen, die von der Layout<T>
Klasse abgeleitet wird, ist es nicht immer praktisch, dies insbesondere für die AbsoluteLayout
Klassen und RelativeLayout
die Klassen Grid
zu tun. Betrachten Sie z. B. das Szenario, in dem eine Sammlung von Daten durch ein gebundenes Layout in einem Grid
angezeigt werden soll, wobei jedes Element in der Sammlung ein Objekt ist, das mehrere Eigenschaften enthält. Jede Zeile im Grid
sollte ein Objekt aus der Sammlung anzeigen, wobei jede Spalte im Grid
eine der Eigenschaften des Objekts anzeigt. Da die DataTemplate
für das bindbare Layout nur ein einzelnes Objekt enthalten kann, muss es sich bei diesem Objekt um eine Layout-Klasse handeln, die mehrere Ansichten enthält, die jeweils eine der Eigenschaften des Objekts in einer bestimmten Grid
-Spalte anzeigen. Dieses Szenario kann zwar mit bindbaren Layouts realisiert werden, führt aber zu einem übergeordneten Grid
, das ein untergeordnetes Grid
für jedes Element in der gebundenen Auflistung enthält. Dies ist eine sehr ineffiziente und problematische Verwendung des Grid
-Layouts.
Auffüllen eines bindbaren Layouts mit Daten
Ein bindbares Layout wird mit Daten aufgefüllt, indem die Eigenschaft ItemsSource
auf eine beliebige Auflistung festgelegt wird, die IEnumerable
implementiert, und an eine Layout<T>
-abgeleitete-Klasse angefügt wird:
<Grid BindableLayout.ItemsSource="{Binding Items}" />
Der entsprechende C#-Code lautet:
IEnumerable<string> items = ...;
var grid = new Grid();
BindableLayout.SetItemsSource(grid, items);
Wenn die angefügte Eigenschaft BindableLayout.ItemsSource
für ein Layout festgelegt wird, aber die angefügte Eigenschaft BindableLayout.ItemTemplate
nicht festgelegt ist, wird jedes Element in der IEnumerable
-Sammlung durch eine Label
angezeigt, die von der BindableLayout
-Klasse erstellt wird.
Definieren der Darstellung des Elements
Die Darstellung der einzelnen Elemente im bindbaren Layout kann durch Festlegen der angefügten Eigenschaft BindableLayout.ItemTemplate
auf eine DataTemplate
definiert werden:
<StackLayout BindableLayout.ItemsSource="{Binding User.TopFollowers}"
Orientation="Horizontal"
...>
<BindableLayout.ItemTemplate>
<DataTemplate>
<controls:CircleImage Source="{Binding}"
Aspect="AspectFill"
WidthRequest="44"
HeightRequest="44"
... />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
Der entsprechende C#-Code lautet:
DataTemplate circleImageTemplate = ...;
var stackLayout = new StackLayout();
BindableLayout.SetItemsSource(stackLayout, viewModel.User.TopFollowers);
BindableLayout.SetItemTemplate(stackLayout, circleImageTemplate);
In diesem Beispiel wird jedes Element in der Auflistung von einer CircleImage
in der TopFollowers
DataTemplate
Folgenden definierten Ansicht angezeigt:
Weitere Informationen zu Datenvorlagen finden Sie unter Xamarin.Forms-Datenvorlagen.
Auswählen der Elementdarstellung zur Runtime
Die Darstellung jedes Elements im bindbaren Layout kann basierend auf dem Elementwert zur Runtime ausgewählt werden, indem die angefügte Eigenschaft BindableLayout.ItemTemplateSelector
auf einen DataTemplateSelector
festgelegt wird:
<FlexLayout BindableLayout.ItemsSource="{Binding User.FavoriteTech}"
BindableLayout.ItemTemplateSelector="{StaticResource TechItemTemplateSelector}"
... />
Der entsprechende C#-Code lautet:
DataTemplateSelector dataTemplateSelector = new TechItemTemplateSelector { ... };
var flexLayout = new FlexLayout();
BindableLayout.SetItemsSource(flexLayout, viewModel.User.FavoriteTech);
BindableLayout.SetItemTemplateSelector(flexLayout, dataTemplateSelector);
Die DataTemplateSelector
in der Beispielanwendung verwendete Anwendung wird im folgenden Beispiel gezeigt:
public class TechItemTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultTemplate { get; set; }
public DataTemplate XamarinFormsTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return (string)item == "Xamarin.Forms" ? XamarinFormsTemplate : DefaultTemplate;
}
}
Die Klasse TechItemTemplateSelector
definiert DefaultTemplate
- und XamarinFormsTemplate
DataTemplate
-Eigenschaften, die auf verschiedene Datenvorlagen festgelegt sind. Die OnSelectTemplate
Methode gibt das XamarinFormsTemplate
Element zurück, das ein Element dunkelrot mit einem Herzen daneben anzeigt, wenn das Element gleich "Xamarin.Forms" ist. Wenn das Element nicht gleich "Xamarin.Forms" ist, gibt die OnSelectTemplate
Methode den DefaultTemplate
Wert zurück, der ein Element mit der Standardfarbe einer :Label
Weitere Informationen zu Datenvorlagenselektoren finden Sie unter Creating a Xamarin.Forms DataTemplateSelector.
Anzeigen einer Zeichenfolge, wenn Daten nicht verfügbar sind
Die Eigenschaft EmptyView
kann auf eine Zeichenfolge festgelegt werden, die von einer Label
angezeigt wird, wenn die ItemsSource
-Eigenschaft null
ist oder wenn die durch die Eigenschaft ItemsSource
angegebene Sammlung null
oder leer ist. Der folgende XAML-Code ist ein Beispiel für dieses Szenario:
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}"
BindableLayout.EmptyView="No achievements">
...
</StackLayout>
Daraus ergibt sich, dass, wenn die datengebundene Auflistung null
ist, die als EmptyView
-Eigenschaftswert festgelegte Zeichenfolge angezeigt wird:
Anzeigen von Ansichten bei nicht verfügbaren Daten
Die Eigenschaft EmptyView
kann auf eine Ansicht festgelegt werden, die angezeigt wird, wenn die Eigenschaft ItemsSource
den Wert null
hat oder wenn die durch die Eigenschaft ItemsSource
angegebene Sammlung null
oder leer ist. Dies kann eine einzelne Ansicht oder eine Ansicht sein, die mehrere untergeordnete Ansichten enthält. Das folgende XAML-Beispiel zeigt die Eigenschaft EmptyView
, die auf eine Ansicht festgelegt ist, die mehrere untergeordnete Ansichten enthält:
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
<BindableLayout.EmptyView>
<StackLayout>
<Label Text="None."
FontAttributes="Italic"
FontSize="{StaticResource smallTextSize}" />
<Label Text="Try harder and return later?"
FontAttributes="Italic"
FontSize="{StaticResource smallTextSize}" />
</StackLayout>
</BindableLayout.EmptyView>
...
</StackLayout>
Das Ergebnis ist, dass, wenn die datengebundene Auflistung null
ist, das StackLayout
und dessen untergeordneten Elemente angezeigt werden.
Ebenso kann die EmptyViewTemplate
auf ein DataTemplate
festgelegt werden, das angezeigt wird, wenn die ItemsSource
-Eigenschaft null
ist, oder wenn die durch die ItemsSource
-Eigenschaft angegebene Auflistung null
oder leer ist. Das DataTemplate
kann eine einzelne Ansicht oder eine Ansicht enthalten, die mehrere untergeordnete Ansichten enthält. Darüber hinaus wird der BindingContext
des EmptyViewTemplate
vom BindingContext
des BindableLayout
geerbt. Das folgende XAML-Beispiel zeigt den Eigenschaftensatz EmptyViewTemplate
, der auf ein DataTemplate
festgelegt ist, das eine einzelne Ansicht enthält:
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
<BindableLayout.EmptyViewTemplate>
<DataTemplate>
<Label Text="{Binding Source={x:Reference usernameLabel}, Path=Text, StringFormat='{0} has no achievements.'}" />
</DataTemplate>
</BindableLayout.EmptyViewTemplate>
...
</StackLayout>
Das Ergebnis ist, dass, wenn die datengebundene Auflistung null
ist, das Label
im DataTemplate
angezeigt wird:
Hinweis
Die Eigenschaft EmptyViewTemplate
kann nicht über einen DataTemplateSelector
festgelegt werden.
Auswählen von EmptyView zur Laufzeit
Ansichten, die als EmptyView
angezeigt werden, wenn keine Daten verfügbar sind, können als ContentView
-Objekte in ResourceDictionary
definiert werden. Die Eigenschaft EmptyView
kann dann zur Laufzeit basierend auf der Geschäftslogik auf eine bestimmte ContentView
festgelegt werden. Der folgende XAML-Code ist ein Beispiel für dieses Szenario:
<ContentPage ...>
<ContentPage.Resources>
...
<ContentView x:Key="BasicEmptyView">
<StackLayout>
<Label Text="No achievements."
FontSize="14" />
</StackLayout>
</ContentView>
<ContentView x:Key="AdvancedEmptyView">
<StackLayout>
<Label Text="None."
FontAttributes="Italic"
FontSize="14" />
<Label Text="Try harder and return later?"
FontAttributes="Italic"
FontSize="14" />
</StackLayout>
</ContentView>
</ContentPage.Resources>
<StackLayout>
...
<Switch Toggled="OnEmptyViewSwitchToggled" />
<StackLayout x:Name="stackLayout"
BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
...
</StackLayout>
</StackLayout>
</ContentPage>
Der XAML-Code definiert zwei ContentView
-Objekte auf der Seitenebene ResourceDictionary
, wobei das Switch
-Objekt steuert, welches ContentView
-Objekt als EmptyView
-Eigenschaftswert festgelegt wird. Wenn Switch
umgeschaltet wird, führt der Ereignishandler OnEmptyViewSwitchToggled
die Methode ToggleEmptyView
aus:
void ToggleEmptyView(bool isToggled)
{
object view = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
BindableLayout.SetEmptyView(stackLayout, view);
}
Die Methode ToggleEmptyView
legt die Eigenschaft EmptyView
des Objekts stackLayout
auf der Grundlage des Werts der Eigenschaft Switch.IsToggled
auf eines der beiden ContentView
-Objekte fest, die in ResourceDictionary
gespeichert sind. Wenn dann die datengebundene Auflistung ist null
, wird das ContentView
als EmptyView
Eigenschaft festgelegte Objekt angezeigt: