Relative Bindungen in Xamarin.Forms
Mit relativen Bindungen kann die Bindungsquelle relativ zur Position des Bindungsziels festgelegt werden. Sie werden mit der Markuperweiterung RelativeSource
erstellt und als Source
-Eigenschaft eines Bindungsausdrucks festgelegt.
Die Markuperweiterung RelativeSource
wird von der Klasse RelativeSourceExtension
unterstützt, in der die folgenden Eigenschaften definiert werden:
Mode
(vom TypRelativeBindingSourceMode
): Gibt den Speicherort der Bindungsquelle relativ zur Position des Bindungsziels an.AncestorLevel
(vom Typint
): Optionale Vorgängerebene, nach der gesucht werden soll, wenn dieMode
-EigenschaftFindAncestor
lautet. Bei einerAncestorLevel
vonn
werdenn-1
Instanzen vomAncestorType
übersprungen.AncestorType
(vom TypType
): Vorgängertyp, nach dem gesucht werden soll, wenn dieMode
-EigenschaftFindAncestor
lautet.
Hinweis
Im XAML-Parser kann die Klasse RelativeSourceExtension
zu RelativeSource
abgekürzt werden.
Die Mode
-Eigenschaft sollte auf einen der Member der Enumeration RelativeBindingSourceMode
festgelegt werden:
TemplatedParent
gibt das Element an, auf das die Vorlage (die das gebundene Element enthält) angewendet wird. Weitere Informationen finden Sie unter An ein übergeordnetes Element mit Vorlagen binden.Self
gibt das Element an, für das die Bindung festgelegt wird. Damit können Sie eine Eigenschaft dieses Elements an eine andere Eigenschaft desselben Elements binden. Weitere Informationen finden Sie unter An sich selbst binden.FindAncestor
gibt das Vorgängerelement in der visuellen Struktur des gebundenen Elements an. Verwenden Sie diesen Modus, um an ein Vorgängersteuerelement zu binden, das von der EigenschaftAncestorType
dargestellt wird. Weitere Informationen finden Sie unter An ein Vorgängerelement binden.FindAncestorBindingContext
gibt dieBindingContext
-Eigenschaft des Vorgängerelements in der visuellen Struktur des gebundenen Elements an. Verwenden Sie diesen Modus, um an dieBindingContext
-Eigenschaft eines Vorgängersteuerelements zu binden, das von der EigenschaftAncestorType
dargestellt wird. Weitere Informationen finden Sie unter An ein Vorgängerelement binden.
Die Mode
-Eigenschaft stellt die Inhaltseigenschaft der Klasse RelativeSourceExtension
dar. Daher können Sie bei XAML-Markupausdrücken (die mit geschweiften Klammern ausgedrückt werden) den Mode=
-Teil des Ausdrucks entfernen.
Weitere Informationen über Xamarin.Forms-Markuperweiterungen finden Sie unter XAML-Markuperweiterungen.
An sich selbst binden
Bei relativen Bindungen wird der Self
-Modus verwendet, um eine Eigenschaft eines Elements an eine andere Eigenschaft desselben Elements zu binden:
<BoxView Color="Red"
WidthRequest="200"
HeightRequest="{Binding Source={RelativeSource Self}, Path=WidthRequest}"
HorizontalOptions="Center" />
In diesem Beispiel wird in der BoxView
-Klasse die Eigenschaft WidthRequest
auf eine feste Größe festgelegt und die Eigenschaft HeightRequest
an die Eigenschaft WidthRequest
gebunden. Beide Eigenschaften sind demnach identisch, und es wird ein Quadrat angezeigt:
Wichtig
Soll eine Eigenschaft eines Elements an eine andere Eigenschaft desselben Elements gebunden werden, müssen die Eigenschaften vom selben Typ sein. Alternativ können Sie für die Bindung einen Konverter angeben, um den Wert zu konvertieren.
Dieser Bindungsmodus wird häufig verwendet, um die BindingContext
-Eigenschafts eines Objekts auf eine Eigenschaft desselben Objekts festzulegen. Im folgenden Code wird ein Beispiel hierfür dargestellt:
<ContentPage ...
BindingContext="{Binding Source={RelativeSource Self}, Path=DefaultViewModel}">
<StackLayout>
<ListView ItemsSource="{Binding Employees}">
...
</ListView>
</StackLayout>
</ContentPage>
In diesem Beispiel wird die BindingContext
Eigenschaft der Seite auf die DefaultViewModel
Eigenschaft derselben Seite festgelegt. Diese Eigenschaft wird in der CodeBehind-Datei für die Seite definiert und stellt eine ViewModel-Instanz bereit. Die ListView
-Klasse wird an die Employees
-Eigenschaft von ViewModel gebunden.
An ein Vorgängerelement binden
Die Modi FindAncestor
und FindAncestorBindingContext
für relative Bindungen werden verwendet, um an übergeordnete Elemente (eines bestimmten Typs) in der visuellen Struktur zu binden. Mit dem FindAncestor
-Modus wird an ein übergeordnetes Element gebunden, das vom Typ Element
abgeleitet wird. Verwenden Sie den FindAncestorBindingContext
-Modus, um an die BindingContext
-Eigenschaft eines übergeordneten Elements zu binden.
Warnung
Bei Verwendung von relativen Bindungen in den Modi FindAncestor
und FindAncestorBindingContext
muss die Eigenschaft AncestorType
auf Type
festgelegt sein. Andernfalls wird eine XamlParseException
ausgelöst.
Wird die Eigenschaft Mode
nicht explizit festgelegt, wird durch Festlegen der Eigenschaft AncestorType
auf einen von Element
abgeleiteten Typ die Mode
-Eigenschaft implizit auf FindAncestor
festgelegt. Wird die AncestorType
-Eigenschaft entsprechend hierzu auf einen Typ festgelegt, der nicht von Element
abgeleitet ist, wird die Mode
-Eigenschaft implizit auf FindAncestorBindingContext
festgelegt.
Hinweis
Relative Bindungen, die den FindAncestorBindingContext
-Modus verwenden, werden erneut angewendet, wenn sich der BindingContext
eines Vorgängers ändert.
Im folgenden XAML-Beispiel wird die Mode
-Eigenschaft implizit auf FindAncestorBindingContext
festgelegt:
<ContentPage ...
BindingContext="{Binding Source={RelativeSource Self}, Path=DefaultViewModel}">
<StackLayout>
<ListView ItemsSource="{Binding Employees}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Fullname}"
VerticalOptions="Center" />
<Button Text="Delete"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:PeopleViewModel}}, Path=DeleteEmployeeCommand}"
CommandParameter="{Binding}"
HorizontalOptions="EndAndExpand" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
In diesem Beispiel wird die BindingContext
Eigenschaft der Seite auf die DefaultViewModel
Eigenschaft derselben Seite festgelegt. Diese Eigenschaft wird in der CodeBehind-Datei für die Seite definiert und stellt eine ViewModel-Instanz bereit. Die ListView
-Klasse wird an die Employees
-Eigenschaft von ViewModel gebunden. Die DataTemplate
-Klasse, die die Darstellung der einzelnen Elemente in ListView
definiert, enthält eine Button
-Klasse. Die Command
-Eigenschaft der Schaltfläche ist an die DeleteEmployeeCommand
-Eigenschaft des übergeordneten ViewModel-Elements gebunden. Durch Tippen auf Button
wird ein Mitarbeiter gelöscht:
Zudem kann die optionale Eigenschaft AncestorLevel
dazu beitragen, die Vorgängersuche in Szenarios eindeutig zu machen, in denen eventuell mehr als ein Vorgängerelement dieses Typs in der visuellen Struktur vorhanden ist:
<Label Text="{Binding Source={RelativeSource AncestorType={x:Type Entry}, AncestorLevel=2}, Path=Text}" />
In diesem Beispiel wird die Eigenschaft Label.Text
an die Eigenschaft Text
der zweiten Entry
-Klasse gebunden. Diese wird im Pfad nach oben beginnend beim Zielelement der Bindung gefunden.
Hinweis
Legen Sie die Eigenschaft AncestorLevel
auf 1 fest, um das dem Bindungszielelement am nächsten gelegene Vorgängerelement zu finden.
An ein übergeordnetes Element mit Vorlagen binden
Der Modus TemplatedParent
für eine relative Bindung wird verwendet, um von einer Steuerelementvorlage an die Instanz eines Laufzeitobjekts zu binden, auf die die Vorlage angewendet wird. Diese wird auch als übergeordnetes Element mit Vorlagen bezeichnet. Dieser Modus kann nur angewendet werden, wenn sich die relative Bindung in einer Steuerelementvorlage befindet. Die Vorgehensweise ähnelt dem Festlegen einer TemplateBinding
-Eigenschaft.
Der folgende XAML-Code zeigt ein Beispiel für eine relative Bindung im TemplatedParent
-Modus:
<ContentPage ...>
<ContentPage.Resources>
<ControlTemplate x:Key="CardViewControlTemplate">
<Frame BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
BackgroundColor="{Binding CardColor}"
BorderColor="{Binding BorderColor}"
...>
<Grid>
...
<Label Text="{Binding CardTitle}"
... />
<BoxView BackgroundColor="{Binding BorderColor}"
... />
<Label Text="{Binding CardDescription}"
... />
</Grid>
</Frame>
</ControlTemplate>
</ContentPage.Resources>
<StackLayout>
<controls:CardView BorderColor="DarkGray"
CardTitle="John Doe"
CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
<controls:CardView BorderColor="DarkGray"
CardTitle="Jane Doe"
CardDescription="Phasellus eu convallis mi. In tempus augue eu dignissim fermentum. Morbi ut lacus vitae eros lacinia."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
<controls:CardView BorderColor="DarkGray"
CardTitle="Xamarin Monkey"
CardDescription="Aliquam sagittis, odio lacinia fermentum dictum, mi erat scelerisque erat, quis aliquet arcu."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
</StackLayout>
</ContentPage>
In diesem Beispiel ist die BindingContext
-Eigenschaft der Frame
-Klasse, die das Stammelement der ControlTemplate
-Eigenschaft darstellt, auf die Instanz des Laufzeitobjekts festgelegt, auf die die Vorlage angewendet wird. Daher lösen die Frame
-Klasse und ihre untergeordneten Elemente ihre Bindungsausdrücke anhand der Eigenschaften der einzelnen CardView
-Objekte auf:
Weitere Informationen zu Steuerelementvorlagen finden Sie unter Xamarin.Forms-Steuerelementvorlagen.