Buscar..


Parámetros

Parámetro Detalles
valor El valor producido por la fuente de enlace.
valores La matriz de valores, producida por la fuente de enlace.
tipo de objetivo El tipo de la propiedad objetivo de enlace.
parámetro El parámetro convertidor a utilizar.
cultura La cultura a utilizar en el convertidor.

Observaciones

Qué son IValueConverter e IMultiValueConverter

IValueConverter e IMultiValueConverter: interfaces que proporcionan una manera de aplicar una lógica personalizada a un enlace.

Para que sirven

  1. Tiene algún valor de tipo pero desea mostrar valores cero de una manera y números positivos de otra manera
  2. Tiene algún valor de tipo y desea mostrar el elemento en un caso y ocultarse en otro
  3. Tienes un valor numérico de dinero pero quieres mostrarlo como palabras
  4. Tiene un valor numérico pero desea mostrar imágenes diferentes para números diferentes

Estos son algunos de los casos simples, pero hay muchos más.

Para casos como este, puede usar un convertidor de valores. Estas clases pequeñas, que implementan la interfaz IValueConverter o IMultiValueConverter, actuarán como intermediarios y traducirán un valor entre la fuente y el destino. Por lo tanto, en cualquier situación en la que necesite transformar un valor antes de que llegue a su destino o vuelva a su origen, es probable que necesite un convertidor.

Construido en BooleanToVisibilityConverter [IValueConverter]

Convertidor entre booleanos y visibilidad. Obtener valor bool en la entrada y devuelve el valor de Visibility .

NOTA: Este convertidor ya existe en el espacio de nombres System.Windows.Controls .

public sealed class BooleanToVisibilityConverter : IValueConverter
{
    /// <summary>
    /// Convert bool or Nullable bool to Visibility
    /// </summary>
    /// <param name="value">bool or Nullable bool</param>
    /// <param name="targetType">Visibility</param>
    /// <param name="parameter">null</param>
    /// <param name="culture">null</param>
    /// <returns>Visible or Collapsed</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool bValue = false;
        if (value is bool)
        {
            bValue = (bool)value;
        }
        else if (value is Nullable<bool>)
        {
            Nullable<bool> tmp = (Nullable<bool>)value;
            bValue = tmp.HasValue ? tmp.Value : false;
        }
        return (bValue) ? Visibility.Visible : Visibility.Collapsed;
    }

    /// <summary>
    /// Convert Visibility to boolean
    /// </summary>
    /// <param name="value"></param>
    /// <param name="targetType"></param>
    /// <param name="parameter"></param>
    /// <param name="culture"></param>
    /// <returns></returns>
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Visibility)
        {
            return (Visibility)value == Visibility.Visible;
        }
        else
        {
            return false;
        }
    }
}

Usando el convertidor

  1. Definir recurso
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
  1. Utilízalo en encuadernación
<Button Visibility="{Binding AllowEditing, 
                             Converter={StaticResource BooleanToVisibilityConverter}}"/>

Convertidor con propiedad [IValueConverter]

Muestre cómo crear un convertidor simple con parámetro a través de la propiedad y luego páselo en la declaración. Convertir el valor bool a la Visibility . Permite invertir el valor del resultado estableciendo la propiedad Inverted en True .

public class BooleanToVisibilityConverter : IValueConverter
{
    public bool Inverted { get; set; }

    /// <summary>
    /// Convert bool or Nullable bool to Visibility
    /// </summary>
    /// <param name="value">bool or Nullable bool</param>
    /// <param name="targetType">Visibility</param>
    /// <param name="parameter">null</param>
    /// <param name="culture">null</param>
    /// <returns>Visible or Collapsed</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool bValue = false;
        if (value is bool)
        {
            bValue = (bool)value;
        }
        else if (value is Nullable<bool>)
        {
            Nullable<bool> tmp = (Nullable<bool>)value;
            bValue = tmp ?? false;
        }

        if (Inverted)
            bValue = !bValue;
        return (bValue) ? Visibility.Visible : Visibility.Collapsed;
    }

    /// <summary>
    /// Convert Visibility to boolean
    /// </summary>
    /// <param name="value"></param>
    /// <param name="targetType"></param>
    /// <param name="parameter"></param>
    /// <param name="culture"></param>
    /// <returns>True or False</returns>
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Visibility)
        {
            return ((Visibility) value == Visibility.Visible) && !Inverted;
        }

        return false;
    }
}

Usando el convertidor

  1. Definir espacio de nombres

xmlns:converters="clr-namespace:MyProject.Converters;assembly=MyProject"

  1. Definir recurso
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityInvertedConverter"
                                         Inverted="False"/>
  1. Utilízalo en encuadernación
<Button Visibility="{Binding AllowEditing, Converter={StaticResource BoolToVisibilityConverter}}"/>

Convertidor simple de agregar [IMultiValueConverter]

Muestre cómo crear un simple convertidor de IMultiValueConverter y use MultiBinding en xaml. Obtener la suma de todos los valores pasados ​​por la matriz de values .

public class AddConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        decimal sum = 0M;

        foreach (string value in values)
        {
            decimal parseResult;
            if (decimal.TryParse(value, out parseResult))
            {
                sum += parseResult;
            }
        }

        return sum.ToString(culture);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Usando el convertidor

  1. Definir espacio de nombres
xmlns:converters="clr-namespace:MyProject.Converters;assembly=MyProject"
  1. Definir recurso
<converters:AddConverter x:Key="AddConverter"/>
  1. Utilízalo en encuadernación
<StackPanel Orientation="Vertical">
    <TextBox x:Name="TextBox" />
    <TextBox x:Name="TextBox1" />
    <TextBlock >
        <TextBlock.Text>
            <MultiBinding Converter="{StaticResource AddConverter}">
                <Binding Path="Text" ElementName="TextBox"/>
                <Binding Path="Text" ElementName="TextBox1"/>
            </MultiBinding>
         </TextBlock.Text>
    </TextBlock>
</StackPanel>

Convertidores de uso con ConverterParameter

Muestre cómo crear un convertidor simple y use ConverterParameter para pasar el parámetro al convertidor. Multiplique el valor por el coeficiente pasado en ConverterParameter.

public class MultiplyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return 0;

        if (parameter == null)
            parameter = 1;

        double number;
        double coefficient;

        if (double.TryParse(value.ToString(), out number) && double.TryParse(parameter.ToString(), out coefficient))
        {
            return number * coefficient;
        }

        return 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Usando el convertidor

  1. Definir espacio de nombres
xmlns:converters="clr-namespace:MyProject.Converters;assembly=MyProject"
  1. Definir recurso
<converters:MultiplyConverter x:Key="MultiplyConverter"/>
  1. Utilízalo en encuadernación
<StackPanel Orientation="Vertical">
    <TextBox x:Name="TextBox" />
    <TextBlock Text="{Binding Path=Text, 
                              ElementName=TextBox, 
                              Converter={StaticResource MultiplyConverter},
                              ConverterParameter=10}"/>
</StackPanel>

Grupo de convertidores multiples [IValueConverter]

Este convertidor encadenará varios convertidores juntos.

public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

En este ejemplo, el resultado booleano de EnumToBooleanConverter se usa como entrada en BooleanToVisibilityConverter .

<local:ValueConverterGroup x:Key="EnumToVisibilityConverter">
    <local:EnumToBooleanConverter/>
    <local:BooleanToVisibilityConverter/>
</local:ValueConverterGroup>

El botón solo estará visible cuando la propiedad CurrentMode esté configurada en Ready .

<Button Content="Ok" Visibility="{Binding Path=CurrentMode, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter={x:Static local:Mode.Ready}"/>

Uso de MarkupExtension con convertidores para omitir la declaración de recurso

Normalmente para usar el convertidor, tenemos que definirlo como recurso de la siguiente manera:

<converters:SomeConverter x:Key="SomeConverter"/>

Es posible omitir este paso definiendo un convertidor como MarkupExtension e implementando el método ProvideValue . El siguiente ejemplo convierte un valor a su negativo:

namespace MyProject.Converters
{
public class Converter_Negative : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return this.ReturnNegative(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return this.ReturnNegative(value);
    }

    private object ReturnNegative(object value)
    {
        object result = null;
        var @switch = new Dictionary<Type, Action> {
            { typeof(bool), () => result=!(bool)value },
            { typeof(byte), () => result=-1*(byte)value },
            { typeof(short), () => result=-1*(short)value },
            { typeof(int), () => result=-1*(int)value },
            { typeof(long), () => result=-1*(long)value },
            { typeof(float), () => result=-1f*(float)value },
            { typeof(double), () => result=-1d*(double)value },
            { typeof(decimal), () => result=-1m*(decimal)value }
        };

        @switch[value.GetType()]();
        if (result == null) throw new NotImplementedException();
        return result;
    }

    public Converter_Negative()
        : base()
    {
    }

    private static Converter_Negative _converter = null;

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (_converter == null) _converter = new Converter_Negative();
        return _converter;
    }
}
}

Usando el convertidor:

  1. Definir espacio de nombres

    xmlns: converters = "clr-namespace: MyProject.Converters; assembly = MyProject"

  2. Ejemplo de uso de este convertidor en enlace

    <RichTextBox IsReadOnly="{Binding Path=IsChecked, ElementName=toggleIsEnabled, Converter={converters:Converter_Negative}}"/>
    

Use IMultiValueConverter para pasar múltiples parámetros a un comando

Es posible pasar varios valores enlazados como un CommandParameter utilizando MultiBinding con un IMultiValueConverter muy simple:

namespace MyProject.Converters
{
    public class Converter_MultipleCommandParameters : MarkupExtension, IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return values.ToArray();
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        private static Converter_MultipleCommandParameters _converter = null;

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (_converter == null) _converter = new Converter_MultipleCommandParameters();
            return _converter;
        }

        public Converter_MultipleCommandParameters()
            : base()
        {
        }
    }
}

Usando el convertidor:

  1. Ejemplo de implementación: método llamado cuando se ejecuta SomeCommand ( nota: DelegateCommand es una implementación de ICommand que no se proporciona en este ejemplo ):

     private ICommand _SomeCommand;
     public ICommand SomeCommand
     {
         get { return _SomeCommand ?? (_SomeCommand = new DelegateCommand(a => OnSomeCommand(a))); }
     }
    
     private void OnSomeCommand(object item)
     {
         object[] parameters = item as object[];
    
         MessageBox.Show(
             string.Format("Execute command: {0}\nParameter 1: {1}\nParamter 2: {2}\nParamter 3: {3}",
             "SomeCommand", parameters[0], parameters[1], parameters[2]));
     }
    
  2. Definir espacio de nombres

xmlns: converters = "clr-namespace: MyProject.Converters; assembly = MyProject"

  1. Ejemplo de uso de este convertidor en enlace

    <Button Width="150" Height="23" Content="Execute some command" Name="btnTestSomeCommand"
         Command="{Binding Path=SomeCommand}" >
         <Button.CommandParameter>
             <MultiBinding Converter="{converters:Converter_MultipleCommandParameters}">
                 <Binding RelativeSource="{RelativeSource Self}" Path="IsFocused"/>
                 <Binding RelativeSource="{RelativeSource Self}" Path="Name"/>
                 <Binding RelativeSource="{RelativeSource Self}" Path="ActualWidth"/>
             </MultiBinding>
         </Button.CommandParameter>
     </Button>
    


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow