このような単純な例では、この答えは「はい」になります (不当に冗長です)。しかし、おそらく、ページには複数の Model オブジェクトが含まれます。ページの状態だけでなく、すべて追跡する必要がある他の複数のモデル オブジェクトがある場合があります。これは ViewModel で行われます。
たとえば、ステータス バーに表示されるログイン ユーザーに関する追加情報や、テキスト ファイルへの変更を検出するために実行されているサービスがある場合があります。
Student オブジェクトを編集するためのフォームがある場合もあります。これらの変更を検証する場合は、変更が検証されるまで Student オブジェクトを直接編集したくないでしょう。このような場合、ViewModel は一時的な保存場所として機能します。
上記の注意:モデルで検証が行われることは珍しくありませんが、その場合でも、フォームの編集中にユーザーが無効な値を入力できるようにしたい場合があります。たとえば、モデルがフィールドで長さゼロの値を許可しない場合でも、ユーザーが値を削除し、別のフィールドに移動して (たとえば、コピーする)、フィールドに戻り、編集を終了(貼り付け)します。モデルに直接結び付けられている場合、検証ロジックは、この「中間」、「まだ完成していない」状態を希望どおりに処理できない場合があります。たとえば、ユーザーが入力を完了して [保存] をクリックするまで、ユーザーに検証エラーを通知したくない場合があります。
また、ボタンのクリックなどを処理するために、ViewModel に Command オブジェクトが含まれている可能性もあります。これらは、モデルでは役に立たないドメイン固有のオブジェクトになります。
ViewModels は、Model オブジェクトをフィルタリングしたり、何らかの形で一時的に「変更」して画面上で役立つものを取得したりする必要がある場合にも役立ちます。たとえば、システム内のすべてのユーザーのリストと、その中のトップ 10 のパフォーマーのリアルタイム リスト (10 秒ごとに更新) を表示したい場合があります。または、レポートのリストと全体的な使用率などを示すグラフを表示したい場合があります。そのデータのフィルタリング、並べ替え、およびカスタマイズは、ViewModel 内で行われます。
一方、モデルは通常、可能な限り純粋です。理想的には、(通常) 永続ストレージ (データベース、またはあなたが持っているもの) にあるものを正確にモデル化するPOCOのみが必要です。永続ストレージに FirstName フィールドと LastName フィールドがある場合、Model も同様です。ViewModel でのみ、それらを組み合わせて Name フィールドを取得します (ビューのニーズに応じて、"First Last" または "Last, First" のいずれか)。
例えば:
namespace Model
{
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Class
{
public string Name { get; set; }
public float Score { get; set; }
}
}
namespace ViewModel
{
public class EditStudentRecordViewModel
{
private Model.Student _student;
private IEnumerable<Model.Class> _studentClasses;
/* Bind your View to these fields: */
public string FullName
{
return _student.LastName + ", " + _student.FirstName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public IEnumerable<Model.Class> PassingClasses
{
get
{
return _studentClasses.Where( c => c.Score >= 78 );
}
}
public IEnumerable<Model.Class> FailingClasses
{
get
{
return _studentClasses.Where( c => c.Score < 78 );
}
}
public void Save()
{
List<string> l_validationErrors = new List<string>();
if ( string.IsNullOrEmpty( this.FirstName ) )
l_validationErrors.Add( "First Name must not be empty." );
if ( string.IsNullOrEmpty( this.LastName ) )
l_validationErrors.Add( "Last Name must not be empty." );
if ( l_validationErrors.Any() )
return;
_student.FirstName = this.FirstName;
_student.LastName = this.LastName;
Model.Utilities.SaveStudent( _student );
}
}
}