WPF:如何在1个绑定中使用2个转换器?

时间:2009-10-20 12:46:58

标签: wpf binding converter

我有一个想要显示/隐藏的控件,具体取决于布尔值。

我有一个NegatedBooleanConverter(将true切换为false,反之亦然),我需要先运行此转换器。 我有一个BooleanToVisibilityConverter,我需要在NegatedBoolConverter之后运行这个转换器。

如何解决此问题?我想在XAML中这样做。

编辑:this is a possible solution.

这似乎不起作用。它首先使用单独的转换器转换值,然后使用转换后的值执行某些操作。

我需要的是:

  • 使用第一个转换器转换值(这将赋予convertedValue)。
  • 将convertedValue转换为第二个转换器,这就是我需要的结果。

10 个答案:

答案 0 :(得分:56)

这就是我所做的:

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
    }

我称之为:

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

我认为也可能是MultiValueConverter。也许我会稍后再试。

答案 1 :(得分:28)

扩展Natrium的绝佳答案......

XAML

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

/// <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> { }

答案 2 :(得分:3)

我们在项目中做的是制作一个常规的BooleanToVisibilityConverter,表示转换器接受一个参数(任何东西,一个字符串,一个int,bool,等等)。如果参数设置,则反转结果,否则,它会吐出常规结果。

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 :(得分:3)

在这种情况下,您不需要转换器链。您只需要一个可配置的转换器。这类似于上面的Carlo答案,但明确定义了真值和假值(这意味着您可以使用相同的转换器进行隐藏,可见或折叠转换)。

[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();
    }
}

然后在XAML中:

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

答案 4 :(得分:1)

再次回答我自己的问题:我多年来一直在使用这个解决方案:http://www.codeproject.com/Articles/15061/Piping-Value-Converters-in-WPF

它为现有的2个转换器制作了一个新的转换器,首先调用第一个,然后调用第二个等等。

我对这个解决方案非常满意。

答案 5 :(得分:0)

我刚刚创建了我称之为ReversedBooleanToVisibilityConverter的东西来基本上做那些2会为你做的但是只需一步。

答案 6 :(得分:0)

要解决这个特定问题,您可以编写自己的BoolToVisibilityConverter,而不是使用两个转换器,它使用ConverterParameter(作为bool)来确定是否否定原始布尔值。

答案 7 :(得分:0)

就个人而言,我只需制作一个完整转换的单个转换器。除非你在其他地方迫切需要转换器(如否定),否则如果转换在一个地方进行一次,则更容易维护(imo)。

答案 8 :(得分:0)

我认为你可能想在这里使用Multiconverter而不是两个独立的转换器。您应该能够重用现有转换器中的逻辑。查看this discussion开始。

答案 9 :(得分:0)

以下是Natriummetao答案的组合,可为您节省一些时间:

print (test['code'].isin(["A", "B", "C", "D", "E"]).sum())
5

以及如何使用它:

public class ComparisonConverter : IValueConverter
{
    public object TrueValue { get; set; } = true;
    public object FalseValue { get; set; } = false;


    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value?.Equals(parameter) == true? TrueValue : FalseValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value?.Equals(TrueValue) == true ? parameter : Binding.DoNothing;
    }
}