web-dev-qa-db-ja.com

XAMLで複数の値コンバーターをチェーンする方法はありますか?

2つの別個の変換を行った後、データコンテキストのプロパティにバインドされた整数値を表示する必要がある状況があります。

  1. 範囲内の値を逆にします(例:範囲は1から100、データコンテキストの値は90、ユーザーには値10が表示されます)
  2. 数値を文字列に変換します

独自のコンバーター(IValueConverterを実装する)を作成することで、両方の手順を実行できることに気付きました。ただし、最初のステップだけを実行する別の値コンバーターが既にあり、2番目のステップはInt32Converterでカバーされています。

これら2つの既存のクラスをチェーンする方法はありますかXAMLでそれらをさらに集約するクラスを作成する必要なしに?

このいずれかを明確にする必要がある場合は、お知らせください。 :)

ありがとう。

116
Mal Ross

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

私が探していたものを正確に見つけました、ジョシュ・スミスの厚意: Piping Value Converters(archive.org link) .

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

素晴らしいもの。ありがとう、ジョシュ。 :)

53
Mal Ross

Townの実装 of Gareth 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>
9
Trevi Awater

はい、コンバーターをチェーンする方法がありますが、見た目は美しくなく、ここでは必要ありません。これを必要とするようになった場合、自分自身にそれが本当に行く方法であると自問してください。独自のコンバーターを作成する必要がある場合でも、Simpleは常に適切に機能します。

特定のケースでは、必要なのは、変換された値を文字列にフォーマットすることだけです。 StringFormat 上のプロパティBindingはあなたの友達です。

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