Подтвердить что ты не робот

WPF: как использовать 2 конвертера в 1 привязке?

У меня есть элемент управления, который я хочу показать/скрыть, в зависимости от значения булева.

У меня есть NegatedBooleanConverter (меняет true на false и наоборот), и мне нужно сначала запустить этот конвертер. У меня есть BooleanToVisibilityConverter, и мне нужно запустить этот конвертер после NegatedBoolConverter.

Как я могу исправить эту проблему? Я хочу сделать это в XAML.

edit: это возможное решение.

Это не работает. Он сначала преобразует значение с отдельными преобразователями, а затем делает что-то с преобразованными значениями.

Что мне нужно:

  • Преобразование значения в первый конвертер (это дает convertValue).
  • Преобразовать convertValue со вторым конвертером, и это тот результат, который мне нужен.
4b9b3361

Ответ 1

Чтобы снова ответить на мой вопрос: я использовал это решение уже много лет: http://www.codeproject.com/Articles/15061/Piping-Value-Converters-in-WPF

Он создает новый конвертер из двух существующих конвертеров, сначала вызывающий первый, а затем второй и т.д. и т.д.

Я очень доволен этим решением.

Ответ 2

Это то, что я сделал:

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, я думаю. Возможно, я попробую это позже.

Ответ 3

Развернувшись на Натриуме большой ответ...

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

Ответ 4

В нашем проекте мы делаем обычный 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
}

Ответ 5

В этом случае вам не нужна цепочка конвертеров. Вам просто нужен настраиваемый конвертер. Это похоже на ответ 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" />

Ответ 6

Я только что создал то, что я назвал ReversedBooleanToVisibilityConverter, чтобы в основном делать то, что эти 2 будут делать для вас, но за один шаг.

Ответ 7

Чтобы решить эту конкретную проблему, вместо использования двух преобразователей вы можете написать свой собственный BoolToVisibilityConverter, который использует ConverterParameter (как bool), чтобы определить, следует ли отрицать исходное логическое значение.

Ответ 8

Лично я бы просто сделал 1 единственный конвертер, который делает полное преобразование. Если вам не нужны конвертеры (например, отрицание) в других местах, будет легче поддерживать (imo), если преобразование выполняется один раз, в одном месте.

Ответ 9

Я думаю, вы можете использовать здесь Multiconverter вместо двух отдельных преобразователей. Вы должны иметь возможность повторно использовать логику из существующих конвертеров. Откроем эту дискуссию для начала.