3

私はMVVMライトを使用しており、ViewModelLocatorを使用して任意のビューモデルを取得できるため、それを使用して値を取得できることを理解しました。

私はこのようなことをしてきました

public class ViewModel1
{
   public ViewModel1()
   {
        var vm2 = new ViewModelLocator().ViewModel2;
        string name = vm2.Name;
   }
}

このようにして、ビュー間を移動する必要がある場合、他の値を簡単に取得できます。これがベストプラクティスになるかどうかはわかりませんが(とても便利なようで、悪い習慣なのかと思います笑)、メッセンジャークラスのものがあることを知っているので、それが私がすべき方法である場合は訴えません。

編集

  static ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            SimpleIoc.Default.Register<ViewModel1>();
SimpleIoc.Default.Register<ViewModel2>();
        }


  [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
         "CA1822:MarkMembersAsStatic",
         Justification = "This non-static member is needed for data binding purposes.")]
        public ViewModel1 ViewModel1
        {
            get
            {
                return ServiceLocator.Current.GetInstance<ViewModel1 >();
            }
        }

編集

これが私が解決しようとしているシナリオです。

価格と店名を追加するビューがあります。店舗名のテキストボックスをクリックすると、別のビューに移動します。このビューには、探しているストアを入力するテキスト ボックスがあり、選択リストを入力すると、そのストアに関するすべての可能な一致と情報が入力されます。

次に、ユーザーは希望する店舗を選択します。それらは「価格を追加」するビューに戻され、店舗名も入力されます。

「追加」ボタンを押すと、価格、店舗名、およびバーコード (これは「価格表示を追加」する前の表示からのもの) を取得し、サーバーに送信します。

ご覧のとおり、さまざまなビューからのデータが必要です。

4

4 に答える 4

1

私はあなたのシナリオが何であるかを理解しようとしています。MVVMlight フォーラムで、この質問に次のコンテキストを追加しました。

「複数の画面に渡して、場合によっては再び戻す必要があるデータがいくつかあります。」

VM 間でデータを渡すために、上記の Matt のように、「ファイア アンド フォーゲット」である限り、MVVMLight の Messenger クラスを使用します。しかし、トリッキーに聞こえるのは、「また戻ってくる可能性がある」というコメントです。

これが必要になるいくつかのシナリオを想像できます。例えば。ウィザード インターフェイス。このような場合、ウィザードが収集するデータをモデル化し、そのモデル オブジェクトを表す同じ VM にすべてのビューをバインドします。

しかし、それはほんの一例です。そのため、もう少しコンテキストを提供していただければ、喜んでお手伝いさせていただきます.

于 2013-08-01T22:25:30.903 に答える
1

はい、コードが機能する限りこれを行うことができますが、将来遭遇する可能性のある大きな潜在的な問題があります。

MVVM パターンを使用するための強力な議論の 1 つは、簡単にテストできるコードを簡単に作成できるということです。コードの上にいると、 と がないと
テストできません。それ自体はそれほど悪いことではないかもしれませんが、このタイプのクラスの強い結合が許容されるという先例を設定しました。将来、あなたがどうなるかViewModel1ViewModelLocatorViewModel2

テストの観点からは、依存関係を注入できるとおそらくメリットがあります。これは、通常、必要な情報の外部オブジェクトをコンストラクターに渡すことを意味します。

これは、次のようなコンストラクタがあることを意味します。

public ViewModel1(string vm2Name)
{
    string name = vm2Name;
}

次のように呼び出します。

var vm1 = new ViewModel1(ViewModelLocator.ViewModel2.name);

他にも考慮すべき問題がいくつかあります。

ViewModelLocatorまた、そのプロパティの 1 つにアクセスするための新しい も作成しています。アプリケーション レベルで定義されたロケーターのインスタンスが既にある可能性があります。追加の不必要なインスタンスを新たに作成している場合は、自分自身 (およびプロセッサ) により多くの作業を作成しています。

必要なのは名前だけである場合、完全なインスタンスが本当に必要ViewModel2ですか? 必要以上に作成して渡すことは避けてください。

アップデート

最初のビュー/VM でストアをキャプチャする場合、その (ID および/または名前) を 2 番目のビューから 2 番目の VM に渡さないのはなぜですか? 2 番目の VM は、2 番目のビューでキャプチャされたデータと共にそれをサーバーに送信できます。

もう 1 つのアプローチは、両方のビューに 1 つのビューモデルを使用することです。これにより、問題全体が解消される場合があります。

于 2013-07-17T13:45:49.527 に答える
1

1 つのビューまたはビュー モデルに、2 つ目の (または追加の) ビューまたはビュー モデルからアクセスする必要があるプロパティがある場合は、これらの共有プロパティを格納する新しいクラスを作成し、このクラスを各ビュー モデルに挿入することをお勧めします (またはロケーター経由でアクセスします)。ここで私の答えを見てください... 2つのビュー - 1つのViewModel

SimpleIoc をまだ使用しているサンプル コードを次に示します。

public ViewModelLocator() 
{  
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);                        
    SimpleIoc.Default.Register<IMyClass, MyClass>();              
}  

public IMyClass MyClassInstance
{
    get{ return ServiceLocator.Current.GetInstance<IMyClass>();}
} 

ここに SimpleIOC のレビューがあります - MVVMLight SimpleIoc の使用方法は?

ただし、コメントで述べたように、サポート/共有クラスを複数のビュー モデルに挿入できるように、Autofac コンテナーを使用するように変更しました。このようにして、共有クラスにアクセスするために Locator をインスタンス化する必要がなくなりました。これはよりクリーンなソリューションだと思います。

これは、MyClass と ViewModels を Autofac コンテナーに登録する方法です。

var builder = new ContainerBuilder();
var myClass = new MyClass();
builder.RegisterInstance(myClass);
builder.RegisterType<ViewModel1>();
builder.RegisterType<ViewModel2>();
_container = builder.Build();
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(_container));   

次に、MyClass のインスタンスを必要とする各 ViewModel (ViewModel1、ViewModel2) は、最初にリンクしたように、それをコンストラクター パラメーターとして追加するだけです。

MyClass は、そのプロパティの必要に応じて PropertyChanged を実装します。

于 2013-08-07T18:26:18.367 に答える