ビューモデル ~ビューとモデルの橋渡し役~
ビューモデルはサーバ側のドメインモデルに対し、ビューモデルは、ビューの問題を解決するモデルと考えればいいでしょう。ユーザーが画面で入力したデータを一時的に格納したり、検証を行ったり、サーバに対して問い合わせを行い、データの検索や更新を行ったりします。
ビューモデルの内部を見ていきましょう。
データバインディング
これまでの連載でも何度か出てきましたが、データバインディングは異なるオブジェクト同士のプロパティの値を同期する仕組みです。例えば図4のようにVisual StudioでXAMLを修正した場合は、XAML側の属性値はプロパティウインドウと同期されているので、どちらかの値を書き換えれば、連動して値が変更されます。
ビューモデルは、ビューの情報をバインドされたビューモデルのプロパティ経由で、ビューの情報を参照します。
さらに、プログラム内部で値が変更された場合にビューに変更を通知するため、INotifyPropertyChangedインターフェースを実装します。プロパティの値が変更された時はPropertyChangedイベントを発生させ、ビューに値が変更されたことを通知します。リスト2に、INotifyPropertyChangedインターフェースを実装したビューモデルのサンプルを示します。記事上では、SearchIdプロパティ、登録日プロパティ、ISBNプロパティの実装は省略しています。完全なコードはダウンロードサンプルを参照してください。
public class MainPageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// 値が変更された際にUIへ変更通知を行います。
/// </summary>
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// オブジェクトに対する変更があったかを管理します。
/// </summary>
public bool HasChange { get; set; }
private int? _Id;
public int? Id
{
get { return _Id; }
set {
if (_Id == value) return;
_Id = value;
// UIに値が変更されたことを通知します。
RaisePropertyChanged("Id");
}
}
private string _タイトル;
public string タイトル
{
get { return _タイトル; }
set {
if (_タイトル == value) return;
_タイトル = value;
// UIに値が変更されたことを通知します。
RaisePropertyChanged("タイトル");
HasChange = true;
}
}
... 略 ...
}
ここで注意したいのが、Idプロパティがint?型になっている点です。モデルの定義としてはIdプロパティは主キーになっているため、int型の必須項目なのですが、ビューの初期状態では何の値にも設定されてほしくないため、int?としています。このようにビューモデルでは、ビューとモデルの差異を吸収する役目も持っています。
また、画面にロードされたプロパティに対する変更があったかを管理するHasChangeプロパティを用意しています。

