7

MVVMパターンに関するいくつかの記事、チュートリアル、ブログ投稿を読みました。しかし、私が理解していないことが1つあります。3つの「レイヤー」を取る:

  • モデル
  • 意見
  • モデルを表示

私がMVVMを理解している限り、モデルには「生の」データが含まれています。たとえば、Studentクラスの場合は名前とアドレスです。ビューモデルは、モデルのデータを表すプロパティをビューに公開します。

ビューモデルのプロパティの例

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

モデルの例

private string name;

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

これは少しばかげているように聞こえるかもしれませんが、これは冗長性を生み出しませんか?モデルとビューモデルに名前を保持する必要があるのはなぜですか?ビューモデルの名前を完全に処理しないのはなぜですか?

4

5 に答える 5

5

このような単純な例では、この答えは「はい」になります (不当に冗長です)。しかし、おそらく、ページには複数の 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 );
        }
    }
}
于 2013-01-09T13:52:57.867 に答える
5

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

それが動作(検証、計算など)を保持する場所です。

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

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

于 2013-01-09T13:51:52.623 に答える
4

ビュー モデルは、ビューに固有でモデルには不要なプロパティを追跡する場所です。

あなたのモデルを取り上げましょうPerson

そして、次のようにPerson呼び出されたのビュー モデルを作成します。PersonViewModel

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

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

Personここで、インスタンスを保存するために使用されるボタンがビューにあるとしましょう。ユーザー エクスペリエンス (UX) を向上させるために、モデルが実際に変更された場合にのみボタンを有効にします。したがって、クラスにINotifyPropertyChangedインターフェースを実装します。Person

public class Person : INotifyPropertyChanged
{
    ...

これで、保存ボタンのプロパティがバインドされるプロパティを公開できますが、そのロジックは人物とはの関係もありません。HasUnsavedChangesPersonEnabled

ここで、ビュー モデルの出番です。次のように、ビュー モデルでこのビュー固有のプロパティを定義します。

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

    public bool HasUnsavedChanges { get; set; }
}

次に、ビュー モデルはインターフェイスのPropertyChangedイベントをサブスクライブし、ビュー モデルのプロパティINotifyPropertyChangedを切り替えます。HasUnsavedChanges

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

INotifyPropertyChangedビューがバインドされているビューモデルに変更が加えられたときにビューが取得できるようにするには、ビューモデルにも実装する必要があることに注意してください。

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

于 2013-01-09T14:02:09.300 に答える
1

MVVM のモデルは、MVP または Model2 MVC とまったく同じです。これは、テーマのバリエーションの影響を受けない、MVC にインスパイアされたパターンの一部です。

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

モデルは単一のインスタンスではありません。そうでないと言う人は誰でもそれでいっぱいです。

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

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

于 2013-01-09T13:59:25.283 に答える
1

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

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

サンプル コードのように、モデルのプロパティを ViewModel で公開する必要はないことに注意してください。これは、モデル レイヤーをビュー レイヤーから完全に分離するための「MVVM ピュアリスト」アプローチですが、代わりにモデル全体をビューに公開することも完全に許容されます。これは、単純でコードの重複がないため、ほとんどの小規模プロジェクトで通常使用するものです。

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

ただし、ビューでモデルのいくつかのプロパティのみが必要な場合、またはプロジェクトが十分に大きく、レイヤーを完全に分離したい場合は、ViewModel を介してモデルのプロパティをビューに公開します。サンプルコードにあるように。

于 2013-01-09T14:06:15.933 に答える