力試し
簡単なプログラムを作成します。 まずは自力でチャレンジしてみましょう。
次のようなクラスがあるとします。
internal class User { public string Name { get; } = "Freddie"; public int Age { get; } = 42; }
このクラスのインスタンスを一つ作り、起動すると画面に名前と年齢を表示する、次のようなプログラムを作成してください。
MVVM の概要
MVVM はソフトウェアアーキテクチャの一つで、ソフトを Model、View、ViewModel の 3 要素で表すものです。 Microsoft による MVVM の説明では、利点がいくつか挙げられていますが、簡単に言うと次のようなことを言っているのだと思います。
- UI とビジネスロジックは疎結合になるので、 お互いに、一方の変更がもう一方に影響しにくい。
- 一般的に UI が絡んでくると単体テストがやりにくいが、 View を分離できるため ViewModel と Model の単体テストがやりやすい。
- デザイナーは View の開発、プログラマは ViewModel と Model の 開発をすることができ、分業しやすい。 (ただ、私は xaml を書けるデザイナーに出会ったことはないです。)
ソフトを Model、View、ViewModel の 3 つに別れるということですが、 それぞれの役割は大まかに次のような役割だと思います。
View
- UI の見た目担当
- コントロールの配置やサイズや色を決定する
ViewModel
- Model が持っている値を、View に伝える
- View で入力された値を、Model に伝える
- ユーザーが入力中の、まだ確定していない値の保持
- ユーザーが入力した値の、ビジネスロジックが絡まない検証
- Model の状態の変化を検知し、View に通知する
Model
こう書くと ViewModel のやることが多いように見えますが、 実際には Model の分量が多くなると思います。
解答例
冒頭の力試しの解答例を示します。 ぜひ、自分の考えたコードと比較してください。
https://github.com/Geroshabu/WpfBootCamp/tree/main/Chapter1/Code/Sample
以降、要点を説明していきます。
ビューモデルの作成
今回の例では、User
クラスがモデルです。
このモデルが持つ名前と年齢の情報を、ビューに表示するために、
ビューモデルが橋渡し役になっています。
ビューモデルの例を下記に示します。 ビューモデルの名前は、「ビューの名前+ViewModel」という名前にすることが多いです。
internal class MainWindowViewModel { private readonly User model = new(); public string Name { get { return model.Name; } } // ...(略)... }
ご覧の通り、ビューモデルは User
インスタンスを持っています。
これがモデルです。
モデルが持つ値を、プロパティ Name
を通じて、ビューに返しています。
ビューとビューモデルの紐づけ
ビューモデルを作っただけでは、画面には表示されません。
ビューとビューモデルを対応付けることが必要です。
まずは、ビューが持つ DataContext
というプロパティに、
ビューモデルを設定する必要があります。
DataContext
へのビューモデルの
セットにはいくつか方法がありますが、
今回は、MainWindow
のコードビハインド (.caml.csファイル) で、
自身の DataContext
プロパティにビューモデルを設定してみます。
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new MainWindowViewModel(); } }
さらに .xaml ファイルでは、ビューモデルの Name
プロパティを、
Label.Content
プロパティにバインディング (紐づけ) しています。
これで、ビューモデルから返された値を、ラベルに表示することができます。
<Label Content="{Binding Name}"/>
.xaml ファイルにこのように書くと、
実行時に Name
というプロパティがあるかを探し、
見つかれば Name
プロパティの値を、Label.Content
の値とします。
どこから探し出すのかというと、DataContext
プロパティに設定した
ビューモデルから探し出します。
ですので、DataContext
プロパティに何も設定していないと、
紐づけがうまくいきません。