2013-01-09 13 views
6

私は、MVVMパターンに関するいくつかの記事、チュートリアル、ブログ記事を読んでいます。しかし、私が理解していないことが1つあります。MVVMのモデルは何ですか?

  • モデル
  • ビュー
  • ビューモデルとしてこれまで私は、モデルは、例えば、「生」のデータが含まれているMVVMを理解しているよう

:3「レイヤー」を撮りますStudentクラスの場合の名前と住所。ビューモデルは、モデルのデータを表すビューにプロパティを公開します。これは少し愚かに聞こえるかもしれないが、これは、冗長性を作成しません

private string name; 

public string Name { 
get { return name; } 
set { name = value; } 
} 

モデルのビューモデル

public string Name { 
get { return model.Name; } 
set { model.Name = value; } 
} 

例におけるプロパティの

例?モデルとビューモデルで名前を保持する必要があるのはなぜですか?ビューモデルの名前を完全に扱わないのはなぜですか?

+1

非常によく質問を置く、方法:明快で簡潔で、サンプルコードが含まれています。 – JDB

答えて

5

このような簡単な例では、この回答は「はい」(不当に重複しています)です。しかし、おそらく、ページには単一のModelオブジェクトだけではないものが含まれています。あなたはページ状態と、すべて追跡されなければならない複数の他のModelオブジェクトを持つかもしれません。これはViewModelで行われます。

たとえば、ステータスバーに表示されるログインユーザーに関する追加情報や、テキストファイルの変更を検出するために実行されるサービスなどがあります。

また、Studentオブジェクトを編集するためのフォームがある場合もあります。これらの変更を検証する場合は、変更が検証されるまでStudentオブジェクトを直接編集する必要はありません。このような場合、ViewModelは一時的な格納場所として機能できます。

上記の注:モデルで検証が行われるのは珍しいことではありませんが、ユーザーがフォームの編集中に無効な値を入力できるようにすることもできます。たとえば、モデルでフィールドの長さゼロの値を許可しない場合でも、ユーザーが値を削除したり、別のフィールドに移動したり(たとえば、コピーするなど)、フィールドに戻り、編集(貼り付け)を完了します。モデルに直接結ばれている場合、検証ロジックは、この「中間」、「未完了」の状態を望みどおりに処理しないことがあります。たとえば、ユーザーが入力を完了して[保存]をクリックするまで、検証エラーを表示したくない場合があります。

また、ボタンのクリックなどを処理するために、ViewModelにCommandオブジェクトがあるとします。これらは、モデルでは役に立たないドメイン固有のオブジェクトです。

ViewModelsは、モデルオブジェクトをフィルタリングしたり、一時的に「変更」して画面上で有用なものを得る必要がある場合にも便利です。たとえば、システム内のすべてのユーザーのリストを、上位10人のパフォーマーの中のリアルタイムのリスト(10秒ごとに更新)と共に表示したい場合があります。または、レポートのリストと、全体的な使用率などを示すグラフを表示することもできます。そのデータのフィルタリング、並べ替え、およびカスタマイズは、ViewModel内で行われます。

一方、モデルは通常、できるだけ純粋です。理想的には、永続的なストレージ(データベース、または何を持っているか)に正確にモデルする(通常は)POCOsだけを欲しいとします。永続ストレージにFirstNameフィールドとLastNameフィールドがある場合は、モデルも同様です。 ViewModelでのみ、それらを結合してNameフィールド(ビューのニーズに応じて、「First Last」または「Last、First」のいずれか)を取得します。例えば

:MVVMで

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); 
     } 
    } 
} 
5

モデルはビジネスロジックを含むオブジェクトグラフです。

ここで、動作(検証、計算など)が行われます。

ViewModelは、UIとその相互作用をモデル化するものです。

これらは異なっており、既存の理由が異なります。パターンのポイントは、表示ロジックをVVM(ViewとViewModel)に分離し、ビジネスロジックを完全に分離することです。

0

モデルはMVPやモデル2 MVCと全く同じです。これは、テーマのバリエーションの影響を受けない、MVCから影響を受けたパターンの一部です。

モデルは、リポジトリ、作業単位、ドメイン/モデルオブジェクト、データマッパー、サービスおよびその他の構造を含むレイヤーです。それらを組み合わせると、特定のアプリケーションのすべてのドメインビジネスロジックを含むモデルレイヤーが作成されます。

モデルは単一インスタンスではありません。そうでなければあなたが誰かがそれでいっぱいです。

MVVMが設計されている特定の用途は、モデルレイヤーまたはビューインスタンスのいずれか、またはその両方を変更できない場合の状況です。

P.S.ViewModelインスタンスをASP.NET MVCのドキュメントとして使用している場合は、MVVMを実際に使用していません。実際には「ビューモデル」はビューであり、「ビュー」はテンプレートである)は、物の名前が異なる単なるModel2 MVCです。彼らは、Railsのようなアーキテクチャを「MVC」として販売したときにちょっと混乱しました。

4

あなたはモデルに必要なビューはないに固有のプロパティを追跡する場所のビューモデルがあります。

あなたのモデルはPersonとしましょう。

そして、あなたはこのようになりますこれは、PersonViewModel呼ばPersonのためのビューモデルを作成します。

public class PersonViewModel 
{ 
    public Person Person { get; set; } 
} 

(あなたが直接このようなモデルを公開したくないかもしれませんが、それはまた別の話ですが、注意してください)

ここで、Personインスタンスを保存するために使用されるビューのボタンがあるとします。より良いユーザーエクスペリエンス(UX)を提供するには、モデルが実際に変更された場合にのみボタンを有効にする必要があります。ですから、PersonクラスのINotifyPropertyChanged interface実装:今

public class Person : INotifyPropertyChanged 
{ 
    ... 

を、あなたは保存ボタンを上Enabledプロパティはに結合するあなたのPersonからHasUnsavedChangesプロパティを公開することもできますが、その論理はにしていません人とやりなさい。ビューモデルの出番

これは、あなたはそうのように、ビューモデルにこのビュー固有のプロパティを定義します。

public class PersonViewModel 
{ 
    public Person Person { get; set; } 

    public bool HasUnsavedChanges { get; set; } 
} 

はその後、あなたのビューモデルはのPropertyChanged eventに加入しますINotifyPropertyChangedインターフェイスを開き、ビューモデルのHasUnsavedChangesプロパティを切り替えます。

次に、バインディングが正しく設定されている場合、モデルで変更が発生したときに保存ボタンが有効または無効になりますが、モデルにはビューに結び付けるロジックがありません。

ビューモデルにもINotifyPropertyChangedを実装する必要があることに注意してください。バインドされているビューモデルが変更されたときにビューをピックアップする必要があります。

ここでも、ポイントはモデルのプロパティとモデルに属さないビュープロパティの組み合わせであるロジックを含むブリッジとして機能します。

1

私はいつもモデルをアプリケーションの「ビルディングブロック」として見てきました。それらは通常、いくつかのプロパティを持つ自己完結型クラスであり、おそらく独自のプロパティのためのいくつかの基本的な検証またはロジックです。

ビューモデルは、アプリケーションをビルドして実行する際に「ビルディングブロック」(モデル)を使用する実際のアプリケーションクラスです。高度な検証、プロセスコマンド、イベントの処理、あらゆる種類のビジネスロジックなどを実行します。

にはがあり、ViewModelでモデルのプロパティを公開することはできませんあなたのサンプルコード。そうすることで、ModelレイヤーとViewレイヤーを完全に分離するため、「MVVM purist」アプローチが可能になりますが、View全体にモデル全体を公開することも可能です。これは、シンプルさとコードの重複の欠如のために、私がほとんどの小規模プロジェクトで通常使用しているものです。そこモデルからの唯一のいくつかのプロパティを表示するには必要とされている場合がある、またはプロジェクトは、私は完全に別個の層を維持したいと思うところに十分な大きさであるならば、私は私のモデルさんを公開しかし場合

public MyModel CurrentModel 
{ 
    get { return _model; } 
    set 
    { 
     if (_model != value) 
     { 
      _model = value; 
      RaisePropertyChanged("CurrentModel"); 
     } 
    } 
} 

あなたのサンプルコードのように、ViewModelを使ってViewにプロパティを追加します。

関連する問題