134

我有一种情况,我需要显示一个整数值,绑定到我的数据上下文中的一个属性,经过两次单独的转换后:

  1. 反转一个范围内的值(例如范围是 1 到 100;datacontext 中的值是 90;用户看到的值是 10)
  2. 将数字转换为字符串

我意识到我可以通过创建自己的转换器(实现 IValueConverter)来完成这两个步骤。但是,我已经有了一个单独的值转换器,它只执行第一步,第二步由 Int32Converter 覆盖。

有没有一种方法可以在 XAML中链接这两个现有类,而无需创建另一个聚合它们的类?

如果我需要澄清这些,请告诉我。:)

谢谢。

4

5 回答 5

207

我在我的 Silverlight 项目中使用了 Gareth Evans 的这种方法

这是我的实现:

public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
    #region IValueConverter Members

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

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

    #endregion
}

然后可以像这样在 XAML 中使用它:

<c:ValueConverterGroup x:Key="InvertAndVisibilitate">
   <c:BooleanInverterConverter/>
   <c:BooleanToVisibilityConverter/>
</c:ValueConverterGroup>
于 2011-11-30T12:48:25.623 回答
54

找到了我正在寻找的东西,由 Josh Smith 提供:管道值转换器 (archive.org 链接)

他定义了一个ValueConverterGroup类,它在 XAML 中的使用正是我所希望的。这是一个例子:

<!-- Converts the Status attribute text to a SolidColorBrush used to draw 
     the output of statusDisplayNameGroup. -->
<local:ValueConverterGroup x:Key="statusForegroundGroup">
  <local:IntegerStringToProcessingStateConverter  />
  <local:ProcessingStateToColorConverter />
  <local:ColorToSolidColorBrushConverter />
</local:ValueConverterGroup> 

好东西。谢谢,乔希。:)

于 2010-06-28T08:08:25.700 回答
9

TownGareth Evans 的 Silverlight 项目的实现很棒,但是它不支持不同的转换器参数。

我对其进行了修改,以便您可以提供以逗号分隔的参数(当然,除非您将它们转义)。

转换器:

public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
    private string[] _parameters;

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if(parameter != null)
            _parameters = Regex.Split(parameter.ToString(), @"(?<!\\),");

        return (this).Aggregate(value, (current, converter) => converter.Convert(current, targetType, GetParameter(converter), culture));
    }

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

    private string GetParameter(IValueConverter converter)
    {
        if (_parameters == null)
            return null;

        var index = IndexOf(converter as IValueConverter);
        string parameter;

        try
        {
            parameter = _parameters[index];
        }

        catch (IndexOutOfRangeException ex)
        {
            parameter = null;
        }

        if (parameter != null)
            parameter = Regex.Unescape(parameter);

        return parameter;
    }
}

注意:此处未实现 ConvertBack,完整版本请参阅我的Gist

执行:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:converters="clr-namespace:ATXF.Converters;assembly=ATXF" x:Class="ATXF.TestPage">
  <ResourceDictionary>
    <converters:ValueConverterGroup x:Key="converters">
      <converters:ConverterOne />
      <converters:ConverterTwo />
    </converters:ValueConverterGroup>
  </ResourceDictionary>

  <Label Text="{Binding InitialValue, Converter={StaticResource converters}, ConverterParameter='Parameter1,Parameter2'}" />
</ContentPage>
于 2018-01-29T14:18:24.723 回答
6

是的,有一些方法可以链接转换器,但它看起来并不漂亮,你在这里不需要它。如果你需要这个,问问自己这真的是要走的路吗?即使您必须编写自己的转换器,简单总是效果更好。

在您的特定情况下,您需要做的就是将转换后的值格式化为字符串。StringFormata 上的财产Binding是你的朋友。

 <TextBlock Text="{Binding Value,Converter={StaticResource myConverter},StringFormat=D}" />
于 2010-04-24T09:33:33.097 回答
1

这是Town支持多绑定的答案的一个小扩展:

public class ValueConverterGroup : List<IValueConverter>, IValueConverter, IMultiValueConverter
{
    #region IValueConverter Members

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

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

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return Convert(values as object, targetType, parameter, culture);
    }

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

    #endregion
}
于 2019-09-19T10:24:04.567 回答