【WPF】Binding入門5。DataTriggerの活用

C#

こんにちは、働くC#プログラマーのさんさめです。

WPFにおいてBindingは
「データとビューの疎結合化」
「コード記述の省力化」
などなど非常に重要な役割を果たします。
(後者は慣れないと恩恵を感じにくいですが)

その一方で、
何が起きているのか分かりにくいため、
一度Bindingでハマってしまうと
「まずどこから調べればいいのか分からない」
ということになりがちです。

そこで、私自身の知識の整理も兼ねて
Bindingについてまとめることにしました。

今回はBinding入門編第5回です。

過去の回は以下をご覧ください。

この記事は以下のような人に向けて書いています。

  • データの見せ方を工夫しようとして
    ViewModelのプロパティが大量になった
  • 1回しか使わないようなConverterが
    量産されて管理が大変

本記事では、上記の悩みを解決する、
「DataTrigger」という概念に絞って解説します。

さんさめ
さんさめ

xamlだけでさくっと
変換処理を書けるように
なるのが目標です

スポンサーリンク

DataTriggerはBindingした値に応じてプロパティを変化させる概念

DataTrigger(データトリガー)とは、
Bindingした値に応じてプロパティを変化させる仕組みです。

Style.Triggersプロパティの中に含めることができます。

Style?Triggers?
前提知識が多くない?

はい、いきなりDataTriggerの説明をしてしまいましたが、
順を追って説明しましょう。

そもそもStyleとは、
共通のプロパティを持つコントロールに対して、
設定を共通化、…つまりコントロールを配置するたびに
記述しなければいけないといった手間を
減らすための仕組みです。

より詳しい説明は
かずきのBlog – WPF4.5入門 その50 「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だけでサッと書ける
    • そのため特定の時のみ使う変換がしたい時に便利
  • 見た目を凝るならまずデータートリガー
    • リファクタリングの時にコンバーターを検討

最後までお読みいただき、ありがとうございました。

コメント

タイトルとURLをコピーしました