こんにちは、働くC#プログラマーのさんさめです。
WPFにおいてBindingは
「データとビューの疎結合化」
「コード記述の省力化」
などなど非常に重要な役割を果たします。
(後者は慣れないと恩恵を感じにくいですが)
その一方で、
何が起きているのか分かりにくいため、
一度Bindingでハマってしまうと
「まずどこから調べればいいのか分からない」
ということになりがちです。
そこで、私自身の知識の整理も兼ねて
Bindingについてまとめることにしました。
今回はBinding入門編第5回です。
過去の回は以下をご覧ください。
- 【WPF】Binding入門1。DataContextの伝搬
- 【WPF】Binding入門2。Binding対象を変更するには
- 【WPF】Binding入門3。Converterでデータを変換
- 【WPF】Binding入門4。ユーザーコントロールとBinding
この記事は以下のような人に向けて書いています。
- データの見せ方を工夫しようとして
ViewModelのプロパティが大量になった - 1回しか使わないようなConverterが
量産されて管理が大変
本記事では、上記の悩みを解決する、
「DataTrigger」という概念に絞って解説します。
xamlだけでさくっと
変換処理を書けるように
なるのが目標です
DataTriggerはBindingした値に応じてプロパティを変化させる概念
DataTrigger(データトリガー)とは、
Bindingした値に応じてプロパティを変化させる仕組みです。
Style.Triggersプロパティの中に含めることができます。
Style?Triggers?
前提知識が多くない?
はい、いきなりDataTriggerの説明をしてしまいましたが、
順を追って説明しましょう。
そもそもStyleとは、
共通のプロパティを持つコントロールに対して、
設定を共通化、…つまりコントロールを配置するたびに
記述しなければいけないといった手間を
減らすための仕組みです。
Styleでは、通常、
「Setter」というオブジェクトを配置して
プロパティの値を定義します。
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
</Style>
「Setter」に対し「Triggers」では、
条件を記述し、その条件にマッチしたときのみ
設定される値を定義できます。
次のサンプルでは、
「Triggers」の中に、コントロールが持つプロパティ値を条件とする、
「Trigger」を使って条件を記述しています。
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
<Style.Triggers>
<!-- 無効状態なら背景色を青に -->
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="Blue"/>
</Trigger>
</Style.Triggers>
</Style>
さて、「Triggers」の中には、
上記サンプルに挙げた「Trigger」だけでなく、
別のものを含めることができます。
そこで出てくるのが、Bindingされた値を条件にできる
「DataTrigger」というわけです。
ようやくDataTriggerの
説明に移れる
もう一度、繰り返しになってしまいますが、
DataTrigger(データトリガー)とは、
Bindingした値に応じてプロパティを変化させる仕組みです。
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
<Style.Triggers>
<!-- Nameプロパティが空文字かnullなら背景色を青に -->
<DataTrigger Binding="{Binding Name}" Value="">
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
<DataTrigger Binding="{Binding Name}" Value="{x:Null}">
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
上記サンプルを見ていただくと分かるように、
Bindingされた値と設定される値が
別の型の時に特に効力を発揮します。
しかし、これはある意味Converterでもできることですね。
あえてこちらを使うケースはどのような場合でしょうか。
Converterとの使い分け
通常、色を設定するためのBrushクラスなどは、
Viewの世界の要素です。
つまりBindingするためにこのBrush型のプロパティを
ViewModelの世界に持ち込むのは
密結合となってしまうため避けるべきです。
ということは、Converterしか知らない場合、
Converterを使ってBindingの段階で解決するようにし
依存を切り離したくなるわけですね。
ところが、今回の例のように、
あまりにも特定のコントロール専用の
Converterを作ってしまうと
- クラスの数が増えてしまい管理しづらい
- xamlだけを見ても挙動が予測しづらい
といったデメリットが目立ってしまいます。
つまり、
- 「boolをVisibilityに変換する」
- 「boolを単に反転させる」
といったどこでも使いうるような
汎用的な変換はConverterで行うべきですが…。
- 「文字入力が無い時はToolTipで説明を表示」
- 「数値が0の時だけ文字色を赤に」
みたいな、
使用箇所が限定される変換は、
DataTriggerを使ってxamlに直接記述した方が、
無用なクラスが増えず、
後から見た時にコードを読み解く手間も減らせる
…ということになります。
汎用変換はConverter
特化変換はDataTrigger
凝った見た目にしたい時はまずDataTrigger
DataTriggerの基本的な説明は以上です。
Bindingしている値に応じて
見た目やツールチップなどを変えたい場合、
最初に検討する機構がDataTriggerです。
私もまずはDataTriggerで実装しています。
そして、
「なんか似たような変換処理毎回書いてるな~」
と思ったら、Converterに処理を書き替えていくのが、
実装→リファクタリングの黄金パターンです。
まとめ
まとめです。
- データトリガーを使うと、
バインディングで取得した値を条件に
任意のプロパティの値を変更できる - コンバーターと違ってxamlだけでサッと書ける
- そのため特定の時のみ使う変換がしたい時に便利
- 見た目を凝るならまずデータートリガー
- リファクタリングの時にコンバーターを検討
最後までお読みいただき、ありがとうございました。
シリーズ記事
Binding入門はシリーズ記事となっております。
全ての記事に以下からアクセスできます
コメント