Xamarin.Forms-Bindungspfad
In allen vorherigen Datenbindungsbeispielen wurde die Path
-Eigenschaft der Binding
-Klasse (bzw. die Path
-Eigenschaft der Binding
-Markuperweiterung) auf eine einzelne Eigenschaft festgelegt. Es ist tatsächlich möglich, Path
auf eine untergeordnete Eigenschaft (die Eigenschaft einer Eigenschaft) oder auf einen Collectionmember festzulegen.
Angenommen beispielsweise, Ihre Seite enthält einen TimePicker
-Wert:
<TimePicker x:Name="timePicker">
Die Time
-Eigenschaft von TimePicker
ist vom Typ TimeSpan
. Vielleicht möchten Sie aber eine Datenbindung erstellen, die auf die TotalSeconds
-Eigenschaft dieses TimeSpan
-Werts verweist. So sieht die Datenbindung aus:
{Binding Source={x:Reference timePicker},
Path=Time.TotalSeconds}
Die Eigenschaft Time
ist vom Typ TimeSpan
, der eine Eigenschaft vom Typ TotalSeconds
aufweist. Die Eigenschaften Time
und TotalSeconds
sind einfach durch einen Punkt miteinander verbunden. Die Elemente in der Path
-Zeichenfolge verweisen immer auf Eigenschaften und nicht auf die Typen dieser Eigenschaften.
Dieses Beispiel wird zusammen mit einigen anderen Beispielen auf der Seite Path Variations (Pfadvariationen) angezeigt:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:globe="clr-namespace:System.Globalization;assembly=netstandard"
x:Class="DataBindingDemos.PathVariationsPage"
Title="Path Variations"
x:Name="page">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="10, 0">
<TimePicker x:Name="timePicker" />
<Label Text="{Binding Source={x:Reference timePicker},
Path=Time.TotalSeconds,
StringFormat='{0} total seconds'}" />
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children.Count,
StringFormat='There are {0} children in this StackLayout'}" />
<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
Path=DateTimeFormat.DayNames[3],
StringFormat='The middle day of the week is {0}'}" />
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
<x:Arguments>
<x:String>fr-FR</x:String>
</x:Arguments>
</globe:CultureInfo>
</Binding.Source>
</Binding>
</Label.Text>
</Label>
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children[1].Text.Length,
StringFormat='The second Label has {0} characters'}" />
</StackLayout>
</ContentPage>
Im zweiten Label
-Element stellt die Seite selbst die Bindungsquelle dar. Die Eigenschaft Content
ist vom Typ StackLayout
. Ihr ist eine Children
Eigenschaft vom Typ IList<View>
zugeordnet, die eine Count
-Eigenschaft aufweist. Diese gibt die Anzahl der untergeordneten Eigenschaften an.
Pfade mit Indexer
Die Bindung im dritten Label
-Element auf der Seite Path Variations (Pfadvariationen) verweist auf die CultureInfo
-Klasse im Namespace System.Globalization
:
<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
Path=DateTimeFormat.DayNames[3],
StringFormat='The middle day of the week is {0}'}" />
Die Quelle ist auf die statische CultureInfo.CurrentCulture
-Eigenschaft festgelegt, bei der es sich um ein Objekt vom Typ CultureInfo
handelt. Diese Klasse definiert eine Eigenschaft mit dem Namen DateTimeFormat
vom Typ DateTimeFormatInfo
, die eine DayNames
-Collection enthält. Der Index wählt das vierte Element aus.
Das vierte Label
-Element geht ähnlich vor, jedoch für die mit Frankreich assoziierte Kultur. Die Eigenschaft Source
der Bindung wird mit einem Konstruktor auf das Objekt CultureInfo
festgelegt:
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
<x:Arguments>
<x:String>fr-FR</x:String>
</x:Arguments>
</globe:CultureInfo>
</Binding.Source>
</Binding>
</Label.Text>
</Label>
Weitere Einzelheiten zur Angabe von Konstruktorargumenten in XAML finden Sie unter Übergeben von Konstruktorargumenten.
Das letzte Beispiel ist schließlich mit dem zweiten vergleichbar. Der einzige Unterschied ist, dass auf eines der untergeordneten Elemente von StackLayout
verwiesen wird:
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children[1].Text.Length,
StringFormat='The first Label has {0} characters'}" />
Bei diesem untergeordneten Element handelt es sich um ein Label
-Element, das die Eigenschaft Text
vom Typ String
aufweist, der die Eigenschaft Length
zugeordnet ist. Das erste Label
-Element meldet die in TimePicker
festgelegte TimeSpan
. Wenn dieser Text geändert wird, ändert sich folglich auch das endgültige Label
-Element.
Dies ist das Programm, das ausgeführt wird:
Debuggen komplexer Pfade
Die Erstellung komplexer Pfaddefinitionen kann sich als schwierig erweisen: Sie müssen den Typ der einzelnen untergeordneten Eigenschaften oder den Typ der Elemente in der Collection kennen, um die nächste untergeordnete Eigenschaft ordnungsgemäß hinzufügen zu können. Allerdings werden die Typen selbst nicht im Pfad angezeigt. Eine gute Methode besteht darin, den Pfad inkrementell zu erstellen und sich die Zwischenergebnisse anzusehen. Im letzten Beispiel konnten Sie starten, ohne dass für Path
eine Definition vorhanden war:
<Label Text="{Binding Source={x:Reference page},
StringFormat='{0}'}" />
Hier wird der Typ der Bindungsquelle oder DataBindingDemos.PathVariationsPage
angezeigt. Sie wissen, dass das PathVariationsPage
-Element von ContentPage
abgeleitet wird. Folglich verfügt es über eine Content
-Eigenschaft:
<Label Text="{Binding Source={x:Reference page},
Path=Content,
StringFormat='{0}'}" />
Als Typ der Content
-Eigenschaft wird jetzt Xamarin.Forms.StackLayout
angezeigt. Wenn Sie die Eigenschaft Children
zur Eigenschaft Path
hinzufügen, lautet der Typ Xamarin.Forms.ElementCollection'1[Xamarin.Forms.View]
. Dies ist eine interne Klasse von Xamarin.Forms, aber natürlich auch ein Sammlungstyp. Wenn Sie einen Index hinzufügen, lautet der Typ Xamarin.Forms.Label
. Fahren Sie auf diese Weise fort.
Während Xamarin.Forms den Bindungspfad verarbeitet, wird für jedes Objekt im Pfad ein PropertyChanged
-Handler installiert, der die Schnittstelle INotifyPropertyChanged
implementiert. Beispiel: Die endgültige Bindung reagiert auf eine Änderung im ersten Label
-Element, da sich die Eigenschaft Text
ändert.
Wenn eine Eigenschaft im Bindungspfad INotifyPropertyChanged
nicht implementiert, werden sämtliche an dieser Eigenschaft vorgenommenen Änderungen ignoriert. Durch einige Änderungen könnte der Bindungspfad vollständig ungültig gemacht werden. Daher sollten Sie dieses Verfahren nur dann anwenden, wenn die Zeichenfolge der Eigenschaften und untergeordneten Eigenschaften niemals ungültig wird.