WPF の XAML で Convert を複数個呼び出したい!

常々XAML の Convert を複数個呼び出したいが何かないかなぁ…と考えていたが見つからなかったため、しょうがなく「ViewModel側で変換して、XAMLでConvertして…」という不毛なことをやっていた

しかし!やり方が見つかった!それもあのChatGTPさん!たまには役に立つじゃん!やるじゃん!

てな感じです。


下記の動作は、TabControl を使っていますが、TabControl外に連動した表示・非表示を切り替えたい場合の例です。
・TabIndex は 0~の数字を使用しています。
・TabIndex の 0~は定数化しています。(Constants.TabIndexA/Constants.TabIndexB)
・TabIndex は Service側で管理し、全ViewModel共通で参照できるようにしています。

動作イメージ:
1.ユーザがTabを変更した場合、TabIndex の値が0/1… に変更されます。
2.TabIndex が変更された場合、EqualsConverter を使って、ConverterParameter で指定された値と同じかどうかを判断します。
 同じ場合はtrue、異なる場合はfalse を返却します。
3.2.で変換されたtrue/false の値を元に BooleanToVisibilityConverter を使って、「true:Visible」、「false:Collapsed」を返却します。
4.3.の結果をVisibility に設定することで、ユーザが選んだTabに合わせて、TabControl外の項目を非表示に設定できます。


やり方:
1.Converter を作る
public class CompositeConverter : IValueConverter
{
    /// <summary>
    /// 1番目に呼び出すコンバーター
    /// </summary>
    public IValueConverter Converter1 { get; set; }
    /// <summary>
    /// 2番目に呼び出すコンバーター
    /// </summary>
    public IValueConverter Converter2 { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        object intermediateValue = null;
        if (Converter1 != null)
        {
            intermediateValue = Converter1.Convert(value, targetType, parameter, culture);
        }
        if (Converter2 != null)
        {
            intermediateValue = Converter2.Convert(intermediateValue, targetType, parameter, culture);
        }
        return intermediateValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        object intermediateValue = null;
        // 逆変換なので処理も逆にする
        if (Converter2 != null)
        {
            intermediateValue = Converter2.ConvertBack(value, targetType, parameter, culture);
        }
        if (Converter1 != null)
        {
            intermediateValue = Converter1.ConvertBack(intermediateValue, targetType, parameter, culture);
        }
        return intermediateValue;
    }
}


2.XAMLに宣言をする
<ResourceDictionary>
    <converters:EqualsConverter x:Key="convEquals"/>
    <converters:BooleanToVisibilityConverter x:Key="convBooleanToVisibility" True="Visible" False="Collapsed"/>
    <converters:CompositeConverter x:Key="CompositeEqualsVisibility" 
                                   Converter1="{StaticResource convEquals}" 
                                   Converter2="{StaticResource convBooleanToVisibility}" />
</ResourceDictionary>


3.XAMLで実際に使う
Visibility="{Binding TabIndex.Value, 
                     Converter={StaticResource CompositeEqualsVisibility}, 
                     ConverterParameter={x:Static coreConstants:Constants.TabIndexA}}"



1.のコンバーターは自作してください。
 今は2個しか書いてませんが、3個以上も追加すればよいですし、リストにすれば何個でも行けるんじゃないでしょうか。
 (リストはXAML側が面倒なので嫌ですが…)

2.のXAML宣言は、既存のコンバーターをまずは宣言します。
 宣言した2個のコンバーターを呼び出す順番に設定することで対応できます。

3.は普通に呼び出してください。
 「ConverterParameter」は通常は使わないと思います。


コメント頂ければ、気が付いたときにわかりやすく回収します。

・.Net6
・Prism
・ReactiveProperty



2025年05月22日追記
ChatGTPさんやるじゃん!って思ってたけどやっぱりだめじゃん…でした
XAMLのサンプルコード出して貰ったら、普通にXMALにコンバーターを2個書いてました。
「あれ?XAMLからコンバーターを2個呼び出すのは出来ないんじゃないの?」って言ったら「ご指摘の通りできません!」ときたもんだ…
調子のいい営業さん勘弁してっ!

/**********************************************************************************
本記事はGooブログから作成者本人が移行しました。
 **********************************************************************************/

コメント

このブログの人気の投稿

ヨドバシカメラの店舗購入履歴を見るには…

C# の WPF の DataGrid で 行を交互に背景色を変える+選択色を変える+カラムが無い所も変える…

Visual Studio の ホットリロードが動かない場合に確認するところ