4
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
    var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>();
    adventurerWindowVM.Adv = message.Argument;
    var adventurerWindow = new AdventurerView() 
    {
        DataContext = adventurerWindowVM
    };
    adventurerWindow.Show();
});

このコードはかなり単純です。新しいウィンドウを開き、新しいウィンドウの DataContext を設定するだけです。私が抱えている問題は、これを 2 回実行するとadventurerWindowVM、両方のウィンドウの DataContext であり、このコードが呼び出されるたびに上書きされるため、最初のインスタンスの内容が上書きされ、2 番目のインスタンスの内容に設定されることです。これを防ぐ方法を探しています。このメッセージを使用して複数のウィンドウを開き、それぞれを一意にしたいのですが、これまでのところ、その方法がわかりません。アドバイスをいただければ幸いです。あいまいなタイトルで申し訳ありません。私はこの質問に何と名前を付けるべきか確信が持てませんでした。(また、これがメソッドではないことも知っています。このコード ブロックは何と呼ばれますか?)

更新:私は MVVM Light を使用しています。私のコードは、この回答で誰かが私に提供した例に基づいています: https://stackoverflow.com/a/16994523/1667020

ここに私の ViewModelLocator.cs からのいくつかのコードがあります

public ViewModelLocator()
{
    _main = new MainViewModel();

    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
    SimpleIoc.Default.Register<GameViewModel>();
    SimpleIoc.Default.Register<AdventurerViewModel>();
}
4

4 に答える 4

10

他の答えを与えたので、ここで使用されている IoC コンテナーはSimpleIoCMvvmLight からのものであり、VM の新しいインスタンスを取得するにはGetInstance(...)、インスタンスを解決しようとするたびに一意のキーを渡すだけでよいと思います。 VMの。

切り替えることができるので

var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>();

var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>(System.Guid.NewGuid().ToString());

ただし、MVVMLight Hereの作成者が述べているように、これらの VM はキャッシュされるため、不要になったら削除する必要があります。あなたの場合、おそらくWindowが閉じているときです。

したがって、ラムダ全体を次のようにします。

Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
    var uniqueKey = System.Guid.NewGuid().ToString();
    var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>(uniqueKey);
    adventurerWindowVM.Adv = message.Argument;
    var adventurerWindow = new AdventurerView() 
    {
        DataContext = adventurerWindowVM
    };
    adventurerWindow.Closed += (sender, args) => SimpleIoc.Default.Unregister(uniqueKey);
    adventurerWindow.Show();
});

ノート:

( new AdventurerViewModel() ) を使用して自分で新しい VM を作成する場合に比べて、これは 3 行ほど長くなりますが、IoC コンテナーを使用して VM の LifeTime を管理する場合は、VM の LifeTime を完全に管理する必要があるため、私はこれを好みます。必要のないミックスアンドマッチはあまり好きではありません。むしろ、IoC コンテナーが本来の目的を実行し続けるようにします。

VM インジェクションとライフタイム管理をさらに制御する必要がある場合は、Unityなどのより洗練された Ioc コントローラーを参照してください。SimpleIoCIoC の種類のコンテナーで簡単に足を「濡らす」ことを意図しており、その点で非常にうまく機能します。

于 2013-06-08T07:41:35.843 に答える
3

複数のビューでViewModelの同じインスタンスを使用しようとしていると思います。したがって、ビューは明らかにお互いのビューモデルの内容を上書きします。

これを行うとどうなりますか。

        Messenger.Default.Register<OpenWindowMessage>(this, message =>
    {
        var adventurerWindowVM = new AdventurerViewModel();
        adventurerWindowVM.Adv = message.Argument;
        var adventurerWindow = new AdventurerView() 
        {
            DataContext = adventurerWindowVM
        };
        adventurerWindow.Show();
    });
于 2013-06-08T02:40:36.183 に答える
2

これは、ラムダ式を使用して匿名メソッドを渡すメソッド呼び出しです。

AdventurerViewModelある種の IoC コンテナから取得しているようです。IoC コンテナーはどのように構成されていますか? 特に、返されるオブジェクトの範囲は何ですか? たとえば、IoC がシングルトン スコープでオブジェクトを作成するように構成されている場合、毎回同じオブジェクトへの参照が常に返されます。毎回新しいコピーが返されるように、IoC コンテナーでオブジェクトのスコープを構成する必要がある場合があります。

その方法は、IoC コンテナーによって異なります。どの IoC フレームワークを使用しているか、その構成を確認しなければ、これ以上コメントすることはできません。

于 2013-06-08T02:38:54.897 に答える