Sie sind auf Seite 1von 14

Conversor de valores vinculantes

 01/05/2018
 10 minutos para leer
 Colaboradores
o

Los enlaces de datos generalmente transfieren datos de una propiedad de


origen a una propiedad de destino y, en algunos casos, de la propiedad de
destino a la propiedad de origen. Esta transferencia es sencilla cuando las
propiedades de origen y destino son del mismo tipo, o cuando un tipo se puede
convertir al otro tipo a través de una conversión implícita. Cuando ese no es el
caso, debe realizarse una conversión de tipo.

En el artículo String Formatting , vio cómo puede usar


la StringFormat propiedad de un enlace de datos para convertir cualquier tipo
en una cadena. Para otros tipos de conversiones, necesita escribir algún código
especializado en una clase que implemente la IValueConverter interfaz. (La
plataforma universal de Windows contiene una clase similar
nombrada IValueConverter en el Windows.UI.Xaml.Data espacio de nombres,
pero IValueConverter está en el Xamarin.Forms espacio de nombres). Las clases
que implementan IValueConverter se llaman convertidores de valores , pero
también se conocen como convertidores vinculantes o convertidores de valores
vinculantes .
La interfaz IValueConverter
Supongamos que desea definir un enlace de datos donde la propiedad de
origen es de tipo int pero la propiedad de destino es a bool . Desea que este
enlace de datos produzca un false valor cuando la fuente entera es igual a 0, y
de lo true contrario.

Puedes hacer esto con una clase que implemente la IValueConverter interfaz:
DO#Dupdo

public class IntToBoolConverter : IValueConverter


{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
return (int)value != 0;
}

public object ConvertBack(object value, Type targetType, object


parameter, CultureInfo culture)
{
return (bool)value ? 1 : 0;
}
}

Establece una instancia de esta clase en la Converter propiedad de


la Binding clase o en la Converter propiedad de la Binding extensión de
marcado. Esta clase se convierte en parte del enlace de datos.

El Convert método se invoca cuando los datos se mueven desde el origen al


destino en OneWay o TwoWay enlaces. El value parámetro es el objeto o valor de la
fuente de enlace de datos. El método debe devolver un valor del tipo del
destino de enlace de datos. El método que se muestra aquí arroja
el value parámetro a an int y luego lo compara con 0 para un bool valor de
retorno.

El ConvertBack método se invoca cuando los datos se mueven del objetivo a la


fuente en TwoWay o OneWayToSource enlaces. ConvertBack realiza la conversión
opuesta: asume que el value parámetro es a bool del objetivo, y lo convierte en
un int valor de retorno para la fuente.

Si el enlace de datos también incluye una StringFormat configuración, se invoca


el convertidor de valor antes de formatear el resultado como una cadena.

La página Habilitar botones en el ejemplo Demostraciones de enlace de


datos demuestra cómo usar este convertidor de valor en un enlace de
datos. Se IntToBoolConverter instancia en el diccionario de recursos de la
página. A continuación, se hace referencia a una StaticResource extensión de
marcado para establecer la Converter propiedad en dos enlaces de datos. Es
muy común compartir conversores de datos entre múltiples enlaces de datos en
la página:
XAMLDupdo

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.EnableButtonsPage"
Title="Enable Buttons">
<ContentPage.Resources>
<ResourceDictionary>
<local:IntToBoolConverter x:Key="intToBool" />
</ResourceDictionary>
</ContentPage.Resources>

<StackLayout Padding="10, 0">


<Entry x:Name="entry1"
Text=""
Placeholder="enter search term"
VerticalOptions="CenterAndExpand" />

<Button Text="Search"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
IsEnabled="{Binding Source={x:Reference entry1},
Path=Text.Length,
Converter={StaticResource intToBool}}" />

<Entry x:Name="entry2"
Text=""
Placeholder="enter destination"
VerticalOptions="CenterAndExpand" />

<Button Text="Submit"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
IsEnabled="{Binding Source={x:Reference entry2},
Path=Text.Length,
Converter={StaticResource intToBool}}" />
</StackLayout>
</ContentPage>

Si se utiliza un convertidor de valor en varias páginas de su aplicación, puede


crear una instancia en el diccionario de recursos en el archivo App.xaml .

La página Habilitar botones muestra una necesidad común cuando


se Button realiza una operación basada en el texto que el usuario escribe en
una Entry vista. Si no se ha escrito nada en el Entry , se Button debe
deshabilitar. Cada uno Button contiene un enlace de datos en
su IsEnabled propiedad. La fuente de enlace de datos es Length propiedad de
la Text propiedad del correspondiente Entry . Si esa Length propiedad no es 0,
el convertidor de valor regresa true y Button está habilitado:

Observe que la Text propiedad en cada uno Entry se inicializa en una cadena
vacía. La Text propiedad es null por defecto, y el enlace de datos no funcionará
en ese caso.

Algunos convertidores de valor están escritos específicamente para aplicaciones


particulares, mientras que otros son generalizados. Si sabe que un convertidor
de valor solo se usará en OneWay enlaces, entonces el ConvertBack método
simplemente puede regresar null .

El Convert método mostrado anteriormente supone implícitamente que


el value argumento es de tipo int y el valor de retorno debe ser de
tipo bool . De forma similar, el ConvertBack método supone que
el value argumento es de tipo bool y el valor de retorno es int . Si ese no es el
caso, se producirá una excepción de tiempo de ejecución.

Puede escribir convertidores de valor para que sean más generalizados y acepte
diferentes tipos de datos. Los métodos Convert y ConvertBack pueden usar
los operadores as o is con el value parámetro, o pueden invocar GetType ese
parámetro para determinar su tipo, y luego hacer algo apropiado. El tipo
esperado del valor de retorno de cada método viene dado por
el targetType parámetro. Algunas veces, los convertidores de valor se usan con
enlaces de datos de diferentes tipos de objetivos; el convertidor de valor puede
usar el targetType argumento para realizar una conversión para el tipo correcto.

Si la conversión que se realiza es diferente para diferentes culturas, use


el culture parámetro para este propósito. El parameter argumento
para Convert y ConvertBack se discute más adelante en este artículo.

Propiedades del convertidor vinculante


Las clases de convertidor de valor pueden tener propiedades y parámetros
genéricos. Este convertidor de valor particular convierte a bool desde el origen a
un objeto de tipo T para el objetivo:
DO#Dupdo

public class BoolToObjectConverter<T> : IValueConverter


{
public T TrueObject { set; get; }

public T FalseObject { set; get; }

public object Convert(object value, Type targetType, object parameter,


CultureInfo culture)
{
return (bool)value ? TrueObject : FalseObject;
}

public object ConvertBack(object value, Type targetType, object


parameter, CultureInfo culture)
{
return ((T)value).Equals(TrueObject);
}
}

La página Indicadores de cambio muestra cómo se puede usar para mostrar el


valor de una Switch vista. Aunque es común crear instancias de convertidores
de valor como recursos en un diccionario de recursos, esta página muestra una
alternativa: cada convertidor de valor se crea una instancia
entre Binding.Converter etiquetas de elementos de
propiedad. El x:TypeArguments indica el argumento genérico, y TrueObject ,
y FalseObject se establecen en objetos de ese tipo:
XAMLDupdo
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.SwitchIndicatorsPage"
Title="Switch Indicators">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="18" />
<Setter Property="VerticalOptions" Value="Center" />
</Style>

<Style TargetType="Switch">
<Setter Property="VerticalOptions" Value="Center" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>

<StackLayout Padding="10, 0">


<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand">
<Label Text="Subscribe?" />
<Switch x:Name="switch1" />
<Label>
<Label.Text>
<Binding Source="{x:Reference switch1}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter
x:TypeArguments="x:String"
TrueObject="Of
course!"
FalseObject="No
way!" />
</Binding.Converter>
</Binding>
</Label.Text>
</Label>
</StackLayout>

<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand">
<Label Text="Allow popups?" />
<Switch x:Name="switch2" />
<Label>
<Label.Text>
<Binding Source="{x:Reference switch2}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter
x:TypeArguments="x:String"
TrueObject="Yes"
FalseObject="No" />
</Binding.Converter>
</Binding>
</Label.Text>
<Label.TextColor>
<Binding Source="{x:Reference switch2}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter
x:TypeArguments="Color"
TrueObject="Green"
FalseObject="Red" />
</Binding.Converter>
</Binding>
</Label.TextColor>
</Label>
</StackLayout>

<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand">
<Label Text="Learn more?" />
<Switch x:Name="switch3" />
<Label FontSize="18"
VerticalOptions="Center">
<Label.Style>
<Binding Source="{x:Reference switch3}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter
x:TypeArguments="Style">
<local:BoolToObjectConverter.TrueObject>
<Style TargetType="Label">
<Setter Property="Text"
Value="Indubitably!" />
<Setter Property="FontAttributes"
Value="Italic, Bold" />
<Setter Property="TextColor"
Value="Green" />
</Style>
</local:BoolToObjectConverter.TrueObject>

<local:BoolToObjectConverter.FalseObject>
<Style TargetType="Label">
<Setter Property="Text" Value="Maybe
later" />
<Setter Property="FontAttributes"
Value="None" />
<Setter Property="TextColor"
Value="Red" />
</Style>
</local:BoolToObjectConverter.FalseObject>
</local:BoolToObjectConverter>
</Binding.Converter>
</Binding>
</Label.Style>
</Label>
</StackLayout>
</StackLayout>
</ContentPage>

En el último de los tres Switch y Label pares, el argumento genérico se


establece en Style , y Style se proporcionan objetos enteros para los valores
de TrueObject y FalseObject . Estos reemplazan el estilo implícito para Label set
en el diccionario de recursos, por lo que las propiedades en ese estilo se
asignan explícitamente a Label . Alternar las Switch causas
correspondientes Label para reflejar el cambio:
También es posible usarlo Triggers para implementar cambios similares en la
interfaz del usuario en función de otras vistas.
Parámetros del convertidor de enlace
La Binding clase define una ConverterParameter propiedad y
la Binding extensión de marcado también define
una ConverterParameter propiedad. Si se establece esta propiedad, el valor se
pasa a los métodos Convert y a los ConvertBack métodos
como parameter argumento. Incluso si la instancia del convertidor de valor se
comparte entre varios enlaces de datos, ConverterParameter puede ser diferente
para realizar conversiones algo diferentes.

El uso de ConverterParameter se demuestra con un programa de selección de


color. En este caso, el RgbColorViewModel tiene tres propiedades de
tipo double nombre Red , Green y Blue que se utiliza para construir
un Color valor de:
DO#Dupdo

public class RgbColorViewModel : INotifyPropertyChanged


{
Color color;
string name;

public event PropertyChangedEventHandler PropertyChanged;

public double Red


{
set
{
if (color.R != value)
{
Color = new Color(value, color.G, color.B);
}
}
get
{
return color.R;
}
}

public double Green


{
set
{
if (color.G != value)
{
Color = new Color(color.R, value, color.B);
}
}
get
{
return color.G;
}
}

public double Blue


{
set
{
if (color.B != value)
{
Color = new Color(color.R, color.G, value);
}
}
get
{
return color.B;
}
}

public Color Color


{
set
{
if (color != value)
{
color = value;
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs("Red"));
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs("Green"));
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs("Blue"));
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs("Color"));

Name = NamedColor.GetNearestColorName(color);
}
}
get
{
return color;
}
}

public string Name


{
private set
{
if (name != value)
{
name = value;
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs("Name"));
}
}
get
{
return name;
}
}
}

Los Red , Green y Blue propiedades oscilan entre 0 y 1. Sin embargo, es posible
que prefiera que los componentes se muestran como valores hexadecimales de
dos dígitos.

Para mostrarlos como valores hexadecimales en XAML, se deben multiplicar por


255, convertir a un entero y luego formatearse con una especificación de "X2"
en la StringFormat propiedad. Las primeras dos tareas (multiplicando por 255 y
convirtiendo a un entero) pueden ser manejadas por el convertidor de
valor. Para hacer que el convertidor de valor sea lo más generalizado posible, el
factor de multiplicación se puede especificar con
la ConverterParameter propiedad, lo que significa que ingresa
los métodos Convert y ConvertBack como el parameter argumento:
DO#Dupdo

public class DoubleToIntConverter : IValueConverter


{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
return (int)Math.Round((double)value * GetParameter(parameter));
}

public object ConvertBack(object value, Type targetType, object


parameter, CultureInfo culture)
{
return (int)value / GetParameter(parameter);
}

double GetParameter(object parameter)


{
if (parameter is double)
return (double)parameter;

else if (parameter is int)


return (int)parameter;

else if (parameter is string)


return double.Parse((string)parameter);

return 1;
}
}

Los Convert conversos de a double a int mientras se multiplican por


el parameter valor; el ConvertBack divide
el value argumento entero por parameter y devuelve un double resultado. (En el
programa que se muestra a continuación, el convertidor de valor se usa solo en
conexión con el formato de cadena, por ConvertBack lo que no se utiliza).

El tipo de parameter argumento probablemente sea diferente dependiendo de si


el enlace de datos se define en código o XAML. Si
la ConverterParameter propiedad de Binding está configurada en código, es
probable que se establezca en un valor numérico:
DO#Dupdo

binding.ConverterParameter = 255;

La ConverterParameter propiedad es de tipo Object , por lo que el compilador de


C # interpreta el literal 255 como un entero, y establece la propiedad a ese
valor.

En XAML, sin embargo, ConverterParameter es probable que se establezca así:


XAMLDupdo

<Label Text="{Binding Red,


Converter={StaticResource doubleToInt},
ConverterParameter=255,
StringFormat='Red = {0:X2}'}" />

El 255 parece un número, pero como ConverterParameter es de tipo Object , el


analizador XAML trata el 255 como una cadena.

Por esa razón, el convertidor de valor se muestra arriba incluye una


separada GetParameter método que controla casos para parameter ser de
tipo double , int o string .

La página del selector de color RGB crea una


instancia DoubleToIntConverter en su diccionario de recursos siguiendo la
definición de dos estilos implícitos:
XAMLDupdo

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.RgbColorSelectorPage"
Title="RGB Color Selector">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Slider">
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>

<Style TargetType="Label">
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>

<local:DoubleToIntConverter x:Key="doubleToInt" />


</ResourceDictionary>
</ContentPage.Resources>

<StackLayout>
<StackLayout.BindingContext>
<local:RgbColorViewModel Color="Gray" />
</StackLayout.BindingContext>

<BoxView Color="{Binding Color}"


VerticalOptions="FillAndExpand" />

<StackLayout Margin="10, 0">


<Label Text="{Binding Name}" />

<Slider Value="{Binding Red}" />


<Label Text="{Binding Red,
Converter={StaticResource doubleToInt},
ConverterParameter=255,
StringFormat='Red = {0:X2}'}" />

<Slider Value="{Binding Green}" />


<Label Text="{Binding Green,
Converter={StaticResource doubleToInt},
ConverterParameter=255,
StringFormat='Green = {0:X2}'}" />

<Slider Value="{Binding Blue}" />


<Label>
<Label.Text>
<Binding Path="Blue"
StringFormat="Blue = {0:X2}"
Converter="{StaticResource doubleToInt}">
<Binding.ConverterParameter>
<x:Double>255</x:Double>
</Binding.ConverterParameter>
</Binding>
</Label.Text>
</Label>
</StackLayout>
</StackLayout>
</ContentPage>

Los valores de Red y las Green propiedades se muestran con


una Binding extensión de marcado. La Blue propiedad, sin embargo, una
instancia de la Binding clase para demostrar cómo una explícita double valor se
puede ajustar a ConverterParameter la propiedad.

Das könnte Ihnen auch gefallen