web-dev-qa-db-fra.com

WPF: Comment utiliser 2 convertisseurs dans 1 contraignant?

J'ai un contrôle que je veux montrer/masquer, en fonction de la valeur d'un booléen.

J'ai un Concurreur négatifBoolAncan (commutation fidèle à False et vice versa) et je dois d'abord exécuter ce convertisseur. J'ai un convertisseur de BooleantVisivibilité et j'ai besoin d'exécuter ce convertisseur après la négationBoolConverter.

Comment puis-je résoudre ce problème? Je veux faire cela dans xaml.

eDIT: Ceci est une solution possible.

Cela ne semble pas fonctionner. Il convertit d'abord la valeur avec les convertisseurs séparés, puis fait quelque chose avec les valeurs converties.

Ce dont j'ai besoin est:

  • Convertissez la valeur avec le premier convertisseur (cela donne convertivalue).
  • Convertir ConvertedValue avec le deuxième convertisseur et c'est ce résultat dont j'ai besoin.
42
Natrium

Pour répondre à nouveau à ma propre question: j'utilise cette solution depuis des années maintenant: http://www.codeproject.com/articles/15061/PIPING-VALUE-CONVERTERS-IN-WPF

Il constitue un nouveau convertisseur de 2 convertisseurs existants, appelant la première première, puis le second, etc.

Je suis assez content de cette solution.

1
Natrium

C'est ce que j'ai fait:

public class CombiningConverter : IValueConverter
    {
        public IValueConverter Converter1 { get; set; }
        public IValueConverter Converter2 { get; set; }

        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            object convertedValue = Converter1.Convert(value, targetType, parameter, culture);
            return Converter2.Convert(convertedValue, targetType, parameter, culture);
        }

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

        #endregion
    }

et j'appelle ça comme ça:

<converters:CombiningConverter x:Key="negatedBoolToVisibilityConverter" Converter1="{StaticResource NegatedBooleanConverter}" Converter2="{StaticResource BoolToVisibilityConverter}" />

Un multivalueconverter pourrait également être possible, je pense. Peut-être que je vais essayer cela plus tard.

59
Natrium

Élargir sur la grande réponse de Natitre ...

Xaml

<conv:ConverterChain x:Key="convBoolToInverseToVisibility">
    <conv:BoolToInverseConverter />
    <BooleanToVisibilityConverter />
</conv:ConverterChain>

Classer

/// <summary>Represents a chain of <see cref="IValueConverter"/>s to be executed in succession.</summary>
[ContentProperty("Converters")]
[ContentWrapper(typeof(ValueConverterCollection))]
public class ConverterChain : IValueConverter
{
    private readonly ValueConverterCollection _converters= new ValueConverterCollection();

    /// <summary>Gets the converters to execute.</summary>
    public ValueConverterCollection Converters
    {
        get { return _converters; }
    }

    #region IValueConverter Members

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

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Converters
            .Reverse()
            .Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
    }

    #endregion
}

/// <summary>Represents a collection of <see cref="IValueConverter"/>s.</summary>
public sealed class ValueConverterCollection : Collection<IValueConverter> { }
28
Jake Berger

Dans ce cas, vous n'avez pas besoin d'une chaîne de convertisseur. Vous avez juste besoin d'un convertisseur configurable. Ceci est similaire à la réponse de Carlo ci-dessus, mais définit explicitement les valeurs vraies et fastes (ce qui signifie que vous pouvez utiliser les mêmes convertisseurs pour des conversions cachées, visibles ou effondrées).

[ValueConversion(typeof(bool), typeof(Visibility))]
public class BoolToVisibilityConverter : IValueConverter
{
    public Visibility TrueValue { get; set; }
    public Visibility FalseValue { get; set; }

    public BoolToVisibilityConverter()
    {
        // set defaults
        FalseValue = Visibility.Hidden;
        TrueValue = Visibility.Visible;
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? TrueValue : FalseValue;
    }

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

Puis dans xaml:

    <BoolToVisibilityConverter x:Key="BoolToVisibleConverter"
                               FalseValue="Hidden"
                               TrueValue="Visible" />
3
metao

Ce que nous faisons dans notre projet est de faire un convertisseur régulier de BooleantVisivibilité, ledit convertisseur prend un paramètre (n'importe quoi du tout, une chaîne, un Int, Bool, peu importe). Si le paramètre est défini, il inverse le résultat, sinon, il crache le résultat régulier.

public class BooleanToVisibilityConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool? isVisible = value as bool?;
        if (parameter != null && isVisible.HasValue)
            isVisible = !isVisible;
        if (isVisible.HasValue && isVisible.Value == true)
            return Visibility.Visible;
        else
            return Visibility.Collapsed;
    }

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

    #endregion
}
3
Carlo

Je pense que vous voudrez peut-être utiliser un multiconverteur ici au lieu de deux convertisseurs distincts. Vous devriez être capable de réutiliser la logique à partir de vos convertisseurs existants. Vérifiez cette discussion pour un début.

0
Scott Lawrence

Je viens de créer ce que j'ai appelé inverséboolantantovisibilitéconverter pour faire fondamentalement ce que ces 2 feraient pour vous, mais en une étape.

0
Alan Mendelevich

Pour remédier à ce problème spécifique, au lieu d'utiliser deux convertisseurs, vous pouvez écrire votre propre Concoverter BooltOvisibilité qui utilise le converterParamètre (en tant que BOOL) pour déterminer s'il doit ou non nier le booléen d'origine.

0
John Myczek

Personnellement, je ferais simplement 1 convertisseur unique qui fait la conversion complète. À moins que vous n'ayez désespérément besoin des convertisseurs (comme la négation) dans d'autres endroits, il sera plus facile de maintenir (OMI) si la conversion est effectuée une fois, au même endroit.

0
Alastair Pitts