Modo de enlace
Todas las propiedades enlazables de .NET Multi-platform App UI (.NET MAUI) tienen un modo de enlace predeterminado que se establece cuando se crea la propiedad enlazable, y que está disponible en la propiedad DefaultBindingMode
del objeto BindableProperty. Este modo de enlace predeterminado indica el modo en vigor cuando esa propiedad es un destino de enlace de datos. El modo de enlace predeterminado para la mayoría de las propiedades como Rotation
, Scale
y Opacity
es OneWay
. Cuando estas propiedades son destinos de enlace de datos, la propiedad de destino se establece desde el origen.
En el ejemplo siguiente se muestra un enlace de datos definido en Slider:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.ReverseBindingPage"
Title="Reverse Binding">
<StackLayout Padding="10, 0">
<Label x:Name="label"
Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Slider x:Name="slider"
VerticalOptions="Center"
Value="{Binding Source={x:Reference label},
Path=Opacity}" />
</StackLayout>
</ContentPage>
En este ejemplo, Label es el origen de enlace de datos y Slider es el destino. El enlace hace referencia a la propiedad Opacity
de Label, que tiene un valor predeterminado de 1. Como cabría esperar, Slider se inicializa en el valor 1 a partir del valor inicial Opacity
de Label. Esto se muestra en la captura de pantalla siguiente.
Además, Slider continúa funcionando. Esto se debe a que el modo de enlace predeterminado para la propiedad Value
de Slider es TwoWay
. Esto significa que cuando la propiedad Value
es un destino de enlace de datos, el destino se establece desde el origen, pero el origen también se establece desde el destino. Esto es lo que permite que Slider se establezca en el valor inicial Opacity
.
Nota:
Las propiedades enlazables no señalan un cambio de propiedad a menos que la propiedad cambie realmente. Esto evita un bucle infinito.
Si el modo de enlace predeterminado en la propiedad de destino no es adecuado para un enlace de datos concreto, es posible reemplazarlo si se establece la propiedad Mode
de Binding
(o la propiedad Mode
de la extensión de marcado Binding
) en uno de los miembros de la enumeración BindingMode
.
Default
TwoWay
: los datos van en ambas direcciones entre el origen y el destinoOneWay
: los datos van del origen al destinoOneWayToSource
: los datos van del destino al origenOneTime
: los datos van del origen al destino, pero solo cuando cambiaBindingContext
Enlaces bidireccionales
La mayoría de las propiedades enlazables tienen un modo de enlace predeterminado de OneWay
, pero algunas propiedades tienen un modo de enlace predeterminado de TwoWay
, incluidas las siguientes:
- Propiedad
Date
de DatePicker - Propiedad
Text
de Editor, Entry, SearchBar y EntryCell - Propiedad
IsRefreshing
de ListView - Propiedad
SelectedItem
deMultiPage
- Propiedades
SelectedIndex
ySelectedItem
de Picker - Propiedad
Value
de Slider y Stepper - Propiedad
IsToggled
de Switch - Propiedad
On
de SwitchCell - Propiedad
Time
de TimePicker
Estas propiedades se definen como TwoWay
, porque cuando los enlaces de datos se usan con el patrón Modelo-Vista-Modelo de vista (MVVM), la clase de modelo de vista es el origen del enlace de datos y la vista, que consta de vistas como Slider, son destinos de enlace de datos. Los enlaces de MVVM se parecen al ejemplo anterior, porque es muy probable que quieras que cada vista de la página se inicialice con el valor de la propiedad correspondiente en el modelo de vista, pero los cambios en la vista también deberían afectar a la propiedad de modelo de vista.
Enlaces unidireccionales al origen
Las propiedades enlazables de solo lectura tienen un modo de enlace predeterminado de OneWayToSource
. Por ejemplo, la propiedad SelectedItem
de ListView tiene un modo de enlace predeterminado de OneWayToSource
. La razón es que el resultado de un enlace en la propiedad SelectedItem
debe ser el establecimiento del origen de enlace.
Enlaces de un solo uso
Las propiedades de destino con un modo de enlace de OneTime
solo se actualizan cuando cambia el contexto de enlace. Para los enlaces en estas propiedades de destino, esto simplifica la infraestructura de enlace ya que no es necesario supervisar los cambios en las propiedades de origen.
Varias propiedades enlazables tienen un modo de enlace predeterminado de OneTime
, que incluye la propiedad IsTextPredictionEnabled
de Entry.
Modelos de vista y notificaciones de cambio de propiedad
Cuando se usa un modelo de vista en un enlace de datos, el modelo de vista es el origen de enlace de datos. El modelo de vista no define propiedades enlazables, pero implementa un mecanismo de notificación que permite que la infraestructura de enlace reciba una notificación cuando cambia el valor de una propiedad. Este mecanismo de notificación es la interfaz de INotifyPropertyChanged
, que define un único evento denominado PropertyChanged
. Una clase que implemente esta interfaz normalmente desencadena el evento cuando cambia el valor de una de sus propiedades públicas. No es necesario desencadenar el evento si la propiedad no cambia nunca. La interfaz INotifyPropertyChanged
también se implementa mediante BindableObject y se desencadena un evento PropertyChanged
cada vez que una propiedad enlazable cambia de valor.
En el ejemplo siguiente, los enlaces de datos te permiten seleccionar un color mediante tres elementos Slider para el matiz, la saturación y la luminosidad.
public class HslColorViewModel : INotifyPropertyChanged
{
Color color;
string name;
float hue;
float saturation;
float luminosity;
public event PropertyChangedEventHandler PropertyChanged;
public float Hue
{
get
{
return hue;
}
set
{
if (hue != value)
{
Color = Color.FromHsla(value, saturation, luminosity);
}
}
}
public float Saturation
{
get
{
return saturation;
}
set
{
if (saturation != value)
{
Color = Color.FromHsla(hue, value, luminosity);
}
}
}
public float Luminosity
{
get
{
return luminosity;
}
set
{
if (luminosity != value)
{
Color = Color.FromHsla(hue, saturation, value);
}
}
}
public Color Color
{
get
{
return color;
}
set
{
if (color != value)
{
color = value;
hue = color.GetHue();
saturation = color.GetSaturation();
luminosity = color.GetLuminosity();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Hue"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Saturation"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Luminosity"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));
Name = NamedColor.GetNearestColorName(color);
}
}
}
public string Name
{
get
{
return name;
}
private set
{
if (name != value)
{
name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
}
}
En este ejemplo, la clase HslColorViewModel
define las propiedades: Hue
, Saturation
, Luminosity
, Color
y Name
. Cuando cambia el valor de cualquiera de los tres componentes de color, se vuelve a calcular la propiedad Color
y se desencadenan eventos PropertyChanged
para las cuatro propiedades: Cuando cambia la propiedad Color
, el método estático GetNearestColorName
de la clase NamedColor
obtiene el color con nombre más cercano y establece la propiedad Name
.
Cuando se establece un modelo de vista como un origen de enlace, la infraestructura de enlace adjunta un controlador al evento PropertyChanged
. De esta manera, el enlace puede recibir una notificación de cambios en las propiedades y, después, puede establecer las propiedades de destino a partir de los valores cambiados. Pero cuando una propiedad de destino (o la definición Binding
en una propiedad de destino) tiene un elemento BindingMode
de tipo OneTime
, no es necesario que la infraestructura de enlace adjunte un controlador al evento PropertyChanged
. La propiedad de destino solo se actualiza cuando cambia BindingContext
y no cuando cambia la propiedad de origen.
El código XAML siguiente consume HslColorViewModel
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.SimpleColorSelectorPage">
<ContentPage.BindingContext>
<local:HslColorViewModel Color="MediumTurquoise" />
</ContentPage.BindingContext>
<ContentPage.Resources>
<Style TargetType="Slider">
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<BoxView Color="{Binding Color}"
Grid.Row="0" />
<StackLayout Grid.Row="1"
Margin="10, 0">
<Label Text="{Binding Name}"
HorizontalTextAlignment="Center" />
<Slider Value="{Binding Hue}" />
<Slider Value="{Binding Saturation}" />
<Slider Value="{Binding Luminosity}" />
</StackLayout>
</Grid>
</ContentPage>
En este ejemplo, se crea una instancia de HslColorViewModel
y se establece la propiedad Color
, y se establece como BindingContext
de la página. Los elementos BoxView, Label y tres vistas Slider heredan el contexto de enlace del elemento ContentPage. Todas estas vistas son destinos de enlace que hacen referencia a las propiedades de origen en el modelo de vista. Para la propiedad Color
de BoxView, y la propiedad Text
de Label, los enlaces de datos son OneWay
: las propiedades de la vista se establecen a partir de las propiedades del modelo de vista. Sin embargo, la propiedad Value
de Slider usa un modo de enlace TwoWay
. Esto permite que cada Slider se establezca a partir del modelo de vista, y también que el modelo de vista se establezca a partir de cada Slider.
Cuando se ejecuta por primera vez el ejemplo, BoxView, Label y los tres elementos Slider están establecidos a partir del modelo de vista en función de la propiedad Color
inicial establecida cuando se creó la instancia del modelo de vista.
A medida que se manipulan los controles deslizantes, BoxView y Label se actualizan del modo correspondiente.
Reemplazo del modo de enlace
Si el modo de enlace en la propiedad de destino se puede reemplazar estableciendo la propiedad Mode
de Binding
(o la propiedad Mode
de la extensión de marcado Binding
) en uno de los miembros de la enumeración BindingMode
.
Sin embargo, el establecimiento de la propiedad Mode
no siempre produce el resultado esperado. Por ejemplo, en el ejemplo siguiente, establecer la propiedad Mode
en TwoWay
no funciona como podrías esperar:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="{Binding Source={x:Reference slider},
Path=Value,
Mode=TwoWay}" />
En este ejemplo, se podría esperar que Slider se inicializara en el valor inicial de la propiedad Scale
, que es 1, pero no es lo que sucede. Cuando se inicializa un enlace TwoWay
, primero se establece el destino a partir del origen, lo que significa que la propiedad Scale
se establece en el valor predeterminado de Slider de 0. Cuando se configura el enlace TwoWay
en el elemento Slider, el elemento Slider se establece inicialmente a partir del origen.
Como alternativa, puedes establecer el modo de enlace en OneWayToSource
:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="{Binding Source={x:Reference slider},
Path=Value,
Mode=OneWayToSource}" />
Ahora se inicializa Slider en 1 (el valor predeterminado de Scale
) pero la manipulación de Slider no afecta a la propiedad Scale
.
Nota:
La clase VisualElement también define las propiedades ScaleX
y ScaleY
, que pueden escalar el elemento VisualElement de forma diferente en dirección horizontal y vertical.
Una aplicación muy útil del reemplazo del modo de enlace predeterminado con un modo de enlace TwoWay
implica la propiedad SelectedItem
de ListView. El modo de enlace predeterminado es OneWayToSource
. Cuando se establece un enlace de datos en la propiedad SelectedItem
para hacer referencia a una propiedad de origen en un modelo de vista, esa propiedad de origen se establece a partir de la selección ListView. Pero en algunas circunstancias, es posible que te interese que también se inicialice ListView a partir del modelo de vista.
Importante
El modo de enlace predeterminado puede variar de control a control y se establece cuando se crea la propiedad enlazable. Está disponible de la propiedad DefaultBindingMode
del objeto BindableProperty.