XAML:ネストされたコンバーター

イントロ


XAML(SilverLight / Wpf / Metro)では、コンバーターはさまざまな目的に使用されます:型変換、文字列の書式設定、複雑なオブジェクトのスカラー値の計算。 プロジェクト内で、関連する問題を解決する多くのコンバータークラスを作成できます(注文ステータスの計算と可視性への変換、注文ステータスのカーソルへの変換、ブール値の可視性/非可視性への変換など)。 重要な状況:異常に複雑なTimeSpanフォーマット用のコンバーターを作成し、今度はDurationを同じ方法でフォーマットする必要があります-同様のコンバーターを作成する必要がありますが、DurationからTimeSpanを事前に解凍します。 文字列の変換には多くのオプションがあり、すべての変換には同じ多くのコンバーターが必要です。

当然、コードを一般化しようとすると、変換がより小さな手順に分割され、その結果、1回だけ使用される2行のコードで構成されるコンバータークラスに遭遇します。

多くの人は、状況を単純化してコードの行数を減らすために、コンバーターチェーンを作成することにより、コンバータークラスではなくXAMLマークアップで変換を結合できることを知りません。 これを行うには、すべての変換を継承する抽象コンバーターを作成します。



実装


独自の抽象変換の前に、別の埋め込みコンバーターの変換を実行するコンバーターを作成しましょう。

クラス宣言:

[ContentProperty("Converter")] public abstract class ChainConverter : IValueConverter
      
      





ContentProperty属性-XAMLマークアップで暗黙的に使用されるプロパティを指定します。

次に、クラスでは、ネストされたコンバーター自体について説明します。

 public IValueConverter Converter { get; set; }
      
      





IValueConverterにすることができます-これにより、既存のコンバーターをネストされたコンバーターとして使用できるようになります。

変換コードは簡単です:

 object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (Converter != null) value = Converter.Convert(value, ThisType ?? targetType, parameter, culture); return Convert(value, targetType, parameter, culture); } public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture);
      
      





thisTypeプロパティについて説明します。 入力で(ネストされたコンバーターの出力で)予期される値の型を宣言します。 サブコンバーターは異なるタイプの値を計算できる場合があり、単純なバインディングの場合に理想的である場合(異なるターゲットタイプに同じコンバーターが使用される場合)、この場合、ネストされたコンバーターにタイプを認識させたくないでしょう究極の目標。 開発中のコンバーターが、バインディングから渡されたtargetType値に応じて動作を変更する他のコンバーターのコンテナーとして使用されないことが確実な場合、このプロパティをオーバーライドできません-デフォルトではnullを返します。 (一般的なケースでは、コンバーターの使用方法がわからず、コンバーターの入力が不足しているため、最悪の場合、コンパイル時エラーまたは実行時エラーを受け取ることができないため、できるだけ頻繁に内部ターゲットタイプを指定することをお勧めします)



使用例


この例では、BoolToVisibilityConverterとInvertBooleanConverterの2つの単純な変換を実装します。 この考えは理解できると思います。trueに設定するとコントロールは非表示になり、falseに設定すると表示されます。

BoolToVisibilityConverterコード:

 public class BoolToVisibilityConverter : ChainConverter { public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (bool) value ? Visibility.Visible : Visibility.Collapsed; } public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotSupportedException(); } }
      
      





InvertBooleanConverterコード:

 public class InvertBooleanConverter : ChainConverter { public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return !(bool) value; } public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotSupportedException(); } }
      
      





使用法:

 <TextBlock Text=" "> <TextBlock.Visibility> <Binding Path="IsChecked" ElementName="checkBox"> <Binding.Converter> <Converters:BoolToVisibilityConverter> <Converters:InvertBooleanConverter /> </Converters:BoolToVisibilityConverter> </Binding.Converter> </Binding> </TextBlock.Visibility> </TextBlock> <CheckBox Content="   " x:Name="checkBox" />
      
      





プロジェクトへのリンク

この手法の使用方法がまだ明確でない場合は、次のコードを想像してください。

 <TextBlock> <TextBlock.Text> <Binding Path="Order"> <Binding.Converter> <TakeFirstNSymbolsConverter SymbolsCount="5"> <OrderStateToStringConverter> <OrderToOrderStateConverter /> </OrderStateToStringConverter> </TakeFirstNSymbolsConverter> </Binding.Converter> </Binding> </TextBlock.Text> </TextBlock>
      
      





ここでは、3つのコンバーターを使用しました:最も深い-OrderToOrderStateConverter-オーダーステータスを計算し、1レベル上に-オーダーステータスを文字列に変換し、最後の(コードの最初)-文字列から最初の5文字を​​抽出します(プロジェクトには、文字列を操作する同様の例があります)。



おわりに


ChainConverterがオンボードの場合、新しいコンバーターを継承するだけです。 ある時点で、新しいコンバーターを作成する代わりに、既に実装されている2つ以上のコンバーターを組み合わせるだけで済みます。

このアプローチにより、コード内で何らかの変換が一度行われると、作業がずっと楽になります。 同じコンバータの組み合わせを複数回使用する場合、新しいクラスを宣言することをお勧めします。 説明したアプローチのおかげで、XAMLマークアップで新しいコンバーターを説明できます。



All Articles