WPFでMVVMを使っていると、
一番分かりづらいのがDataContextです。
最初はシンプルに見えますが、
画面が増えていくにつれて次のような状態になりがちです。
・「このBindingどこ見てる?」
・「なんで値取れない?」
・「さっきまで動いてたのに…」
こういった問題の多くは、
DataContextの流れが見えなくなることが原因です。
この記事では、実務でよくハマる
DataContextの典型パターン3つを整理します。
この記事で分かること
・DataContextで迷子になる原因
・WPFでよくあるバインディング崩壊パターン
・設計で気をつけるポイント
なぜDataContextは分かりづらいのか
WPFではDataContextが親から子へ継承されるため、
構造が深くなるほど「今どこを見ているのか」が分かりづらくなります。
① DataContextがどこから来ているか分からない
WPFのDataContextは 親から子へ継承 されます。
そのため、画面がシンプルなうちは問題ありませんが
構造が深くなると
👉 「今どのViewModelを見ているのか分からない」
という状態になります。
よくあるパターン
・Window → Grid → UserControl → ItemsControl
・途中でDataContextを変更している
問題
・Bindingがどこを参照しているか分からない
・修正時に影響範囲が読めない
回避の考え方
・DataContextを途中でむやみに変えない
・どこで設定しているかを明示する
② DataTemplateで“別世界”になる
ItemsControlやListViewでは
DataTemplate内のDataContextは
👉 コレクションの要素
になります。
よくあるハマり
<Button Command="{Binding CancelCommand}" />
👉 これ、親ViewModelじゃなくて
👉 子アイテムを見ている
結果
・Commandが見つからない
・Bindingエラー
よくある対処(でも複雑化)
Command="{Binding DataContext.CancelCommand,
RelativeSource={RelativeSource AncestorType=Window}}"
👉 動くけど読みにくい
回避の考え方
・子ViewModelにCommandを渡す
・DataContextの階層を浅く保つ
👉 このあたりは、Bindingの複雑化とも強く関係します
関連記事
WPFで後から辛くなるバインディングの典型パターン3選
③ UserControlでDataContextが壊れる
UserControlでよくあるのがこれ。
👉 自分でDataContextを設定してしまう
this.DataContext = this;
問題
・親から渡されたDataContextが消える
・再利用しづらくなる
回避の考え方
・UserControlではDataContextを持たない
・必要ならDependencyPropertyで受け取る
まとめ
WPFでDataContextにハマる原因は
次の3つに集約されることが多いです。
・DataContextの流れが見えない
・DataTemplateで参照先が変わる
・UserControlで上書きしてしまう
これらはすべて
👉 「どこを見ているか分からない」状態
が原因です。
WPFでは
・DataContextを浅くする
・参照を明示する
・責務を分ける
といった点を意識するだけでも
トラブルをかなり減らすことができます。
関連記事
まずはこちら(シリーズの入口)
・WPF・MVVMで最初に覚えておきたいこと|プログラムは「データ」と「処理」だけでは動かない