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:
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.
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.
É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> { }
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" />
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
}
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.
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.
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.
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.