wpf 有没有办法在 XAML 中链接多个值转换器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2607490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:39:44  来源:igfitidea点击:

Is there a way to chain multiple value converters in XAML?

wpfdata-bindingxamlivalueconverter

提问by Mal Ross

I've got a situation in which I need to show an integer value, bound to a property on my data context, after putting it through two separate conversions:

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

  1. Reverse the value within a range (e.g. range is 1 to 100; value in datacontext is 90; user sees value of 10)
  2. convert the number to a string
  1. 反转范围内的值(例如范围是 1 到 100;数据上下文中的值为 90;用户看到的值为 10)
  2. 将数字转换为字符串

I realise I could do both steps by creating my own converter (that implements IValueConverter). However, I've already got a separate value converter that does just the first step, and the second step is covered by Int32Converter.

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

Is there a way I can chain these two existing classes in XAMLwithout having to create a further class that aggregates them?

有没有一种方法可以在 XAML 中链接这两个现有类而不必创建进一步的类来聚合它们?

If I need to clarify any of this, please let me know. :)

如果我需要澄清其中任何一个,请告诉我。:)

Thanks.

谢谢。

回答by Town

I used this methodby Gareth Evans in my Silverlight project.

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

Here's my implementation of it:

这是我的实现:

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
}

Which can then be used in XAML like this:

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

<c:ValueConverterGroup x:Key="InvertAndVisibilitate">
   <c:BooleanInverterConverter/>
   <c:BooleanToVisibilityConverter/>
</c:ValueConverterGroup>

回答by Mal Ross

Found exactly what I was looking for, courtesy of Josh Smith: Piping Value Converters(archive.org link).

找到了我正在寻找的东西,由 Josh Smith 提供:Piping Value Converters (archive.org 链接)

He defines a ValueConverterGroupclass, whose use in XAML is exactly as I was hoping for. Here's an example:

他定义了一个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> 

Great stuff. Thanks, Josh. :)

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

回答by Trevi Awater

Town's implementationof Gareth Evans's Silverlight projectis great, however it does not support different converter parameters.

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

I modified it so you can provide parameters, comma delimited (unless you escape them of course).

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

Converter:

转换器:

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

Note: ConvertBack is not implemented here, see my Gistfor the full version.

注意:这里没有实现 ConvertBack,完整版本请参见我的Gist

Implementation:

执行:

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

回答by wpfwannabe

Yes, there are ways to chain converters but it does not look pretty and you don't need it here. If you ever come to need this, ask yourself is that really the way to go? Simple always works better even if you have to write your own converter.

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

In your particular case, all you need to do is format a converted value to a string. StringFormatproperty on a Bindingis your friend here.

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

 <TextBlock Text="{Binding Value,Converter={StaticResource myConverter},StringFormat=D}" />

回答by Aaron

Here is a small extension of Town's answerto support multi-binding:

这是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
}