Nested binding and piped conversion

自闭症网瘾萝莉.ら 提交于 2019-12-06 08:05:57

Three options:

Option A: Convert your bool to visibility in your multivalueconverter (its just one line)

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    if (values.Length < 2)
        throw new Exception("At least two inputs are needed for comparison");
    bool output = (bool)values.Skip(1).Aggregate(values[0], (x1, x2) =>
         { return x1.Equals(x2); });
    return output ? Visibility.Visible : Visibility.Collapsed;
}


Option B: Use the existing booltovisibilityconverter programatically

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    if (values.Length < 2)
        throw new Exception("At least two inputs are needed for comparison");
    bool output = (bool)values.Skip(1).Aggregate(values[0], (x1, x2) =>
         { return x1.Equals(x2); });
    System.Windows.Controls.BooleanToVisibilityConverter booltovisibilityconverter = new System.Windows.Controls.BooleanToVisibilityConverter();
    return booltovisibilityconverter.Convert(output, System.Type.GetType("System.Boolean"), parameter, culture);
}

PS: You may want to cache the booltovisibilityconverter instead of creating it everytime.

Option C: Pipe your converters
Piping Value Converters in WPF
PS: Beaware that this article is quite old.

H.B.

Based on the idea (see publicgk's answer, option C) that one can create a converter which contains a collection of converters which internally are used in sequence i wrote a shoddy implementation which fits my needs. i.e. i can use a MultiValueConverter at the beginning and pipe the output into a list of normal converters:

[ContentProperty("Converters")]
public class GroupConverter : IValueConverter, IMultiValueConverter
{
    private IMultiValueConverter _multiValueConverter;
    public IMultiValueConverter MultiValueConverter
    {
        get { return _multiValueConverter; }
        set { _multiValueConverter = value; }
    }

    private List<IValueConverter> _converters = new List<IValueConverter>();
    public List<IValueConverter> Converters
    {
        get { return _converters; }
        set { _converters = value; }
    }

    #region IValueConverter Members
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return GroupConvert(value, Converters);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return GroupConvertBack(value, Converters.ToArray().Reverse());
    }

    private static object GroupConvert(object value, IEnumerable<IValueConverter> converters)
    {
        return converters.Aggregate(value, (acc, conv) => { return conv.Convert(acc, typeof(object), null, null); });
    }

    private static object GroupConvertBack(object value, IEnumerable<IValueConverter> converters)
    {
        return converters.Aggregate(value, (acc, conv) => { return conv.ConvertBack(acc, typeof(object), null, null); });
    }
    #endregion

    #region IMultiValueConverter Members
    private InvalidOperationException _multiValueConverterUnsetException =
        new InvalidOperationException("To use the converter as a MultiValueConverter the MultiValueConverter property needs to be set.");

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (MultiValueConverter == null) throw _multiValueConverterUnsetException;
        var firstConvertedValue = MultiValueConverter.Convert(values, targetType, parameter, culture);
        return GroupConvert(firstConvertedValue, Converters);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        if (MultiValueConverter == null) throw _multiValueConverterUnsetException;
        var tailConverted = GroupConvertBack(value, Converters.ToArray().Reverse());
        return MultiValueConverter.ConvertBack(tailConverted, targetTypes, parameter, culture);
    }

    #endregion
}

(As you can see i pretty much completely disregard the ConverterParameters, TargetTypes and CultureInfo parameters, further the ConvertBack methods are untested so i do not advise anyone to actually use this.)

XAML usage:

<vc:GroupConverter MultiValueConverter="{StaticResource EqualityComparisonConv}">
    <StaticResource ResourceKey="BoolToVisibilityConv"/>
</vc:GroupConverter>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!