5

WPFCALMVVMでビューとViewModelを初期化する2つの方法に出くわしました。

1-より人気があるようです。ビューを自動的に解決するには、ViewModelを解決する必要があります。ViewModelには、ビューに関する情報が含まれています。

    public interface IView
    {
        void SetModel(IViewModel model);
    }

    public interface IViewModel
    {
        IView View { get; }
    }

    public class View
    {
        public void SetModel(IViewModel model)
        {
            this.DataContext = model;
        }
    }

    public class ViewModel
    {
        private IView view;

        public ViewModel(IView view)
        {
            this.view = view;
        }

        public IView View { return this.view; }
    }

2-かなりきれいに見え、ViewModelからビューを削除します。ViewModelを自動的に解決するには、ビューを解決する必要があります。オブジェクトをビューに挿入します(これが適切かどうかはわかりません)。

    public interface IView
    {
    }

    public interface IViewModel
    {
    }

    public class View
    {
        private IViewModel model;

        public View(IUnityContainer unityContainer)
        {
            this.model = unityContainer.Resolve<IViewModel>();
            this.DataContext = this.model;
        }
    }

    public class ViewModel
    {
    }

ビューとモデルを初期化するために受け入れられている方法と、各方法の長所と短所は何ですか。ビューにオブジェクトを挿入する必要がありますか?

4

4 に答える 4

3

どちらも有効ですが、#1の方がテスト可能である傾向があります(少なくともテストがより簡潔になります)。#2の利点は、それがより明確になる傾向があり、メンテナンスがもう少し明確になることです。特に、売上高が多い場合は、そのようなことです。説明は少なくなります(これは採用する理由ではありませんが、単なる真実です)。

違いは、#1は依存性注入と呼ばれ、 #2はサービスロケーションと呼ばれることです。どちらも一般的に何らかのIoCコンテナを使用しているため、混乱することがよくあります(ただし、そうである必要はありません)。

最終的には好みの問題ですが、私が言ったように、#1のテストははるかに簡単だと思います...テスト/モックにIUnityContainerインターフェイスを含める必要はありません。

于 2010-01-16T15:58:41.477 に答える
2

オプション1はほぼ正しく見えます。ビューに、ビューモデルへの参照を与えます。

ビューへの参照を含むビューモデルを持っていることは、私には少し怪しいようです。これは、モデルビュープレゼンタータイプのアーキテクチャのように見えます。ビューと激しく相互作用するビューモデルがあり、そのためのビューへの参照が必要な場合は、純粋にデータバインディングに使用されるビューモデルと、より複雑な相互作用を行うプレゼンターにビューモデルを分割する方がよい場合があります。

オプション2はまったく正しく見えません。iocコンテナへの参照をクラスに渡すことは、私の本では大きなコードの臭いです。IoCコンテナへの呼び出しは最小限に抑える必要があります。ほとんどのアプリケーションでは、プログラムの開始時にコンテナを呼び出して、データを接続するだけです。より動的なオブジェクトの作成は、通常、ファクトリクラスを使用して行われます。

于 2010-01-15T15:43:33.877 に答える
2

XAMLでビューモデルを定義し、型付きアクセス用の読み取り専用プロパティを提供することを好みます。

<UserControl ...>
    <UserControl.DataContext>
        <local:MyViewModel/>
    </UserControl.DataContext>

    ...

</UserControl>

public partial class MyView : UserControl, IMyView
{
    public MyViewModel ViewModel
    {
        get { return this.DataContext as MyViewModel; }
    }

    ...
}
于 2010-01-15T16:58:55.820 に答える
1

このコードの問題は、オプション2が必要以上にベイクインしていることです。それは本当に必要ではなく、コンテナへの参照を持つべきではありません。

別の方法では、オプション2をオプション1と同じようにテストできますが、ViewModelがビューを認識しないという点で概念的に明確です。

これは、プリズム領域を使用するのではなく、xmlファイルを使用してレイアウトを指定する場合に特に便利です。これにより、レイアウトを簡単に構成できます。

別:

public interface IView
{
}

public interface IViewModel
{
}

public class View : IView
{
    private IViewModel model;

    public View(IViewModel m)
    {
        this.model = m;
        this.DataContext = this.model;
    }
}

public class ViewModel : IViewModel
{
}

そしてあなたが持っている他のどこか:

Container.RegisterType<IViewModel, ViewModel>( /* appropriate container config */ );
Container.RegisterType<IView, View>(/* appropriate container config */ );

そして、次の方法でどこにでもビューを作成できます。

Container.Resolve<IViewModel>();
于 2011-07-21T03:29:03.507 に答える