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 を作る
2.XAMLに宣言をする
3.XAMLで実際に使う
1.のコンバーターは自作してください。
今は2個しか書いてませんが、3個以上も追加すればよいですし、リストにすれば何個でも行けるんじゃないでしょうか。
(リストはXAML側が面倒なので嫌ですが…)
2.のXAML宣言は、既存のコンバーターをまずは宣言します。
宣言した2個のコンバーターを呼び出す順番に設定することで対応できます。
3.は普通に呼び出してください。
「ConverterParameter」は通常は使わないと思います。
コメント頂ければ、気が付いたときにわかりやすく回収します。
・.Net6
・Prism
・ReactiveProperty
2025年05月22日追記
ChatGTPさんやるじゃん!って思ってたけどやっぱりだめじゃん…でした
XAMLのサンプルコード出して貰ったら、普通にXMALにコンバーターを2個書いてました。
「あれ?XAMLからコンバーターを2個呼び出すのは出来ないんじゃないの?」って言ったら「ご指摘の通りできません!」ときたもんだ…
調子のいい営業さん勘弁してっ!
しかし!やり方が見つかった!それもあの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ブログから作成者本人が移行しました。
**********************************************************************************/
コメント
コメントを投稿