web-dev-qa-db-fra.com

Existe-t-il un moyen de chaîner plusieurs convertisseurs de valeur en XAML?

J'ai une situation dans laquelle j'ai besoin d'afficher une valeur entière, liée à une propriété sur mon contexte de données, après l'avoir mise à travers deux conversions distinctes:

  1. Inversez la valeur dans une plage (par exemple, la plage est de 1 à 100; la valeur dans le contexte de données est de 90; l'utilisateur voit la valeur de 10)
  2. convertir le nombre en chaîne

Je me rends compte que je pourrais faire les deux étapes en créant mon propre convertisseur (qui implémente IValueConverter). Cependant, j'ai déjà un convertisseur de valeur séparé qui ne fait que la première étape, et la deuxième étape est couverte par Int32Converter.

Existe-t-il un moyen de chaîner ces deux classes existantes en XAML sans avoir à créer une autre classe qui les agrège?

Si j'ai besoin de clarifier tout cela, faites-le moi savoir. :)

Merci.

116
Mal Ross

J'ai utilisé cette méthode par Gareth Evans dans mon projet Silverlight.

Voici ma mise en œuvre de celui-ci:

public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

Qui peut ensuite être utilisé en XAML comme ceci:

<c:ValueConverterGroup x:Key="InvertAndVisibilitate">
   <c:BooleanInverterConverter/>
   <c:BooleanToVisibilityConverter/>
</c:ValueConverterGroup>
185
Town

Trouvé exactement ce que je cherchais, gracieuseté de Josh Smith: Piping Value Converters(lien archive.org) .

Il définit une classe ValueConverterGroup, dont l'utilisation en XAML est exactement celle que j'espérais. Voici un exemple:

<!-- Converts the Status attribute text to a SolidColorBrush used to draw 
     the output of statusDisplayNameGroup. -->
<local:ValueConverterGroup x:Key="statusForegroundGroup">
  <local:IntegerStringToProcessingStateConverter  />
  <local:ProcessingStateToColorConverter />
  <local:ColorToSolidColorBrushConverter />
</local:ValueConverterGroup> 

Super truc. Merci, Josh. :)

53
Mal Ross

implémentation de Town of projet Silverlight de Gareth Evans est génial, mais il ne prend pas en charge différents paramètres de convertisseur.

Je l'ai modifié pour que vous puissiez fournir des paramètres délimités par des virgules (sauf si vous y échappez bien sûr).

Convertisseur:

public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
    private string[] _parameters;

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if(parameter != null)
            _parameters = Regex.Split(parameter.ToString(), @"(?<!\\),");

        return (this).Aggregate(value, (current, converter) => converter.Convert(current, targetType, GetParameter(converter), culture));
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    private string GetParameter(IValueConverter converter)
    {
        if (_parameters == null)
            return null;

        var index = IndexOf(converter as IValueConverter);
        string parameter;

        try
        {
            parameter = _parameters[index];
        }

        catch (IndexOutOfRangeException ex)
        {
            parameter = null;
        }

        if (parameter != null)
            parameter = Regex.Unescape(parameter);

        return parameter;
    }
}

Remarque: ConvertBack n'est pas implémenté ici, voir mon Gist pour la version complète.

Implémentation:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.Microsoft.com/winfx/2009/xaml" xmlns:converters="clr-namespace:ATXF.Converters;Assembly=ATXF" x:Class="ATXF.TestPage">
  <ResourceDictionary>
    <converters:ValueConverterGroup x:Key="converters">
      <converters:ConverterOne />
      <converters:ConverterTwo />
    </converters:ValueConverterGroup>
  </ResourceDictionary>

  <Label Text="{Binding InitialValue, Converter={StaticResource converters}, ConverterParameter='Parameter1,Parameter2'}" />
</ContentPage>
9
Trevi Awater

Oui, il existe des moyens de chaîner les convertisseurs, mais cela n'a pas l'air joli et vous n'en avez pas besoin ici. Si jamais vous en avez besoin, demandez-vous si c'est vraiment la voie à suivre? Simple fonctionne toujours mieux même si vous devez écrire votre propre convertisseur.

Dans votre cas particulier, il vous suffit de formater une valeur convertie en chaîne. StringFormat propriété sur un Binding est votre ami ici.

 <TextBlock Text="{Binding Value,Converter={StaticResource myConverter},StringFormat=D}" />
6
wpfwannabe