Enlaces relativos de Xamarin.Forms
Los enlaces relativos proporcionan la capacidad de establecer el origen de enlace en relación con la posición del destino de enlace. Se crean con la extensión de marcado RelativeSource
y se establecen como la propiedad Source
de una expresión de enlace.
La clase RelativeSource
admite la extensión de marcado RelativeSourceExtension
, que define las siguientes propiedades:
Mode
, del tipoRelativeBindingSourceMode
, describe la ubicación del origen de enlace en relación con la posición del destino de enlace.AncestorLevel
, del tipoint
, un nivel de antecesor opcional que se va a buscar, cuando la propiedadMode
esFindAncestor
. UnAncestorLevel
den
omiten-1
instancias delAncestorType
.AncestorType
, del tipoType
, el tipo de antecesor que se va a buscar, cuando la propiedadMode
esFindAncestor
.
Nota:
El analizador de XAML permite abreviar la clase RelativeSourceExtension
como RelativeSource
.
La propiedad Mode
se debe establecer en uno de los miembros de enumeración RelativeBindingSourceMode
.
TemplatedParent
indica el elemento al que se aplica la plantilla, en el que existe el elemento enlazado. Para más información, vea Enlace a un elemento primario con plantilla.Self
indica el elemento en el que se está estableciendo el enlace, lo cual le permite enlazar una propiedad de ese elemento a otra propiedad del mismo elemento. Para más información, vea Enlace a sí mismo.FindAncestor
indica el antecesor en el árbol visual del elemento enlazado. Este modo se debe utilizar para enlazar a un control de antecesor representado por la propiedadAncestorType
. Para más información, vea Enlace a un antecesor.FindAncestorBindingContext
indica elBindingContext
del antecesor en el árbol visual del elemento enlazado. Este modo se debe utilizar para enlazar alBindingContext
de un antecesor representado por la propiedadAncestorType
. Para más información, vea Enlace a un antecesor.
La propiedad Mode
es la propiedad de contenido de la clase RelativeSourceExtension
. Por lo tanto, para las expresiones de marcado XAML expresadas con llaves, puede eliminar la parte Mode=
de la expresión.
Para más información sobre las extensiones de marcado de Xamarin.Forms, vea Extensiones de marcado para el lenguaje XAML.
Enlazar a sí mismo
El modo de enlace relativo Self
se utiliza para enlazar una propiedad de un elemento a otra propiedad del mismo elemento:
<BoxView Color="Red"
WidthRequest="200"
HeightRequest="{Binding Source={RelativeSource Self}, Path=WidthRequest}"
HorizontalOptions="Center" />
En este ejemplo, BoxView
establece su propiedad WidthRequest
en un tamaño fijo y la propiedad HeightRequest
se enlaza a la propiedad WidthRequest
. Por lo tanto, ambas propiedades son iguales y, de este modo, se dibuja un cuadrado:
Importante
Al enlazar una propiedad de un elemento a otra propiedad del mismo elemento, las propiedades deben ser del mismo tipo. También puede especificar un convertidor en el enlace para convertir el valor.
Un uso común de este modo de enlace es establecer la BindingContext
de un objeto en una propiedad en sí misma. El código siguiente muestra un ejemplo de esto:
<ContentPage ...
BindingContext="{Binding Source={RelativeSource Self}, Path=DefaultViewModel}">
<StackLayout>
<ListView ItemsSource="{Binding Employees}">
...
</ListView>
</StackLayout>
</ContentPage>
En este ejemplo, el BindingContext
de la página se establece en la propiedad DefaultViewModel
de sí mismo. Esta propiedad se define en el archivo de código subyacente de la página y proporciona una instancia de ViewModel. El ListView
se enlaza a la propiedad Employees
de ViewModel.
Enlazar a un antecesor
Los modos de enlace relativo FindAncestor
y FindAncestorBindingContext
se usan para enlazar a elementos primarios de un tipo determinado en el árbol visual. El modo FindAncestor
se utiliza para enlazar a un elemento primario, que se deriva del tipo Element
. El modo FindAncestorBindingContext
se utiliza para enlazar a la BindingContext
de un elemento primario.
Advertencia
La propiedad AncestorType
se debe establecer en un Type
al utilizar los modos de enlace relativo FindAncestor
y FindAncestorBindingContext
, de lo contrario se produce una XamlParseException
.
Si no se establece explícitamente la propiedad Mode
, al establecer la propiedad AncestorType
en un tipo que se deriva de Element
se establecerá implícitamente la propiedad Mode
en FindAncestor
. Del mismo modo, si se establece la propiedad AncestorType
en un tipo que no se deriva de Element
, se establecerá implícitamente la propiedad Mode
en FindAncestorBindingContext
.
Nota:
Los enlaces relativos que usan el modo de FindAncestorBindingContext
se volverán a aplicar cuando cambie la BindingContext
de cualquier antecesor.
En el código XAML siguiente se muestra un ejemplo en el que la propiedad Mode
se establecerá implícitamente en FindAncestorBindingContext
:
<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>
En este ejemplo, el BindingContext
de la página se establece en la propiedad DefaultViewModel
de sí mismo. Esta propiedad se define en el archivo de código subyacente de la página y proporciona una instancia de ViewModel. El ListView
se enlaza a la propiedad Employees
de ViewModel. El DataTemplate
, que define la apariencia de cada elemento del ListView
, contiene una Button
. La propiedad Command
del botón está enlazada al DeleteEmployeeCommand
en el ViewModel de su elemento primario. Al pulsar un Button
se elimina un empleado:
Además, la propiedad AncestorLevel
opcional puede ayudar a eliminar la ambigüedad en la búsqueda del antecesor en aquellos escenarios en que sea posible que haya más de un antecesor de ese tipo en el árbol visual.
<Label Text="{Binding Source={RelativeSource AncestorType={x:Type Entry}, AncestorLevel=2}, Path=Text}" />
En este ejemplo, la propiedad Label.Text
se enlaza a la propiedad Text
de la segunda Entry
que se encuentra en la ruta de acceso ascendente, comenzando en el elemento de destino del enlace.
Nota:
La propiedad AncestorLevel
debe establecerse en 1 para buscar el antecesor más próximo al elemento de destino de enlace.
Enlazar a un elemento primario con plantilla
El modo de enlace relativo TemplatedParent
se utiliza para enlazar desde una plantilla de control a la instancia de objeto de tiempo de ejecución a la que se aplica la plantilla (conocida como el elemento primario con plantilla). Este modo solo es aplicable si el enlace relativo está dentro de una plantilla de control y es similar a establecer un TemplateBinding
.
El siguiente XAML muestra un ejemplo de un modo de enlace relativo TemplatedParent
:
<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>
En este ejemplo, la Frame
, que es el elemento raíz del ControlTemplate
, tiene su BindingContext
establecido en la instancia de objeto de tiempo de ejecución a la que se aplica la plantilla. Por lo tanto, Frame
y sus elementos secundarios resuelven sus expresiones de enlace con las propiedades de cada objeto CardView
:
Para obtener más información sobre las plantillas de control, consulte Plantillas de control de Xamarin.Forms.