3

奇妙な問題があります。

GalaSoft の MVVM Light フレームワークを使用していますが、これまでのところすべて正常に動作しています。次のことを試みるまで、メッセンジャーシステムを使用してViewModel間でメッセージを送信しています。

GateKeeperメッセージを送信するシングルトン クラス があります。

このクラスは ViewModel ではないため、 から継承されませんViewModelBase

メッセージを送信しても、どこにも受信されません。

私は次のことを試しました:

  1. からGateKeeper継承さViewModeBaseせます->成功しません。
  2. メッセージを受信するように登録GateKeeperして、実際にそれ自体から送信されたメッセージをキャッチ/受信するかどうかを確認します->成功しません。
  3. GateKeeperシングルトンから通常のインスタンス化への変更-> 成功なし
  4. GateKeeperビューに接続されていない MVVM ViewModel を作成し、 -> no Success のようにメッセージを送信できるようにする

ビューに接続されているすべてのビューモデルはメッセージを送信でき、受信されます。

メッセンジャーが機能する前に、ビューモデルをビューに「リンク」する必要があるように思えますが、imo. それは大きな制限です。

以下は、現在の非常に単純化されたセットアップです。

GateKeeper で ApplicationInitialize を呼び出しても、mainviewmodel または GateKeeper クラス自体で受信したメッセージはトリガーされません。

誰かがこの問題に対する提案をしてくれることを願っています。

ありがとう..

セットアップ例: MainViewModel コンストラクター:

 public MainViewModel()
    {
        Messenger.Default.Register<LoadViewMessage>(this, (message) =>
        {
            if (message.Sender is GateKeeper) CurrentView = message.View;
            else if (message.Sender is LoginViewModel) CurrentView = message.View;
            else if (message.Sender is MenuItemBarViewModel) CurrentView = message.View;
        });

ゲートキーパー:

 public class GateKeeper : IGateKeeper
{
    private readonly IEmployeeService _employeeService;

    #region Implementation of IGateKeeper

    public void ApplicationInitialize()
    {
        Messenger.Default.Send<LoadViewMessage>(new LoadViewMessage(ObjectLocator.MainMapView), this);
    }

    public void LoginSucceeded(Employee employee)
    {
        //This is where we retrieve the available services for the current employee
        //TODO: add methods for retrieving service info from backend

        //Send a message that should make the mainview load the map into its currentview property
        Messenger.Default.Send(new LoadViewMessage(ObjectLocator.MainMapView), this);
    }

    #endregion

    public GateKeeper(IEmployeeService employeeService)
    {
        _employeeService = employeeService;

        //Test.. Is not triggered
        //Just used for debugging, thus nothing happens inhere.
        Messenger.Default.Register<LoadViewMessage>(this, (message) =>
        {
            if (message.Sender is GateKeeper) ;
            else if (message.Sender is LoginViewModel) ;
            else if (message.Sender is MenuItemBarViewModel);
        });
    }

メッセージ クラス: LoadViewMessage

 public class LoadViewMessage : MessageBase
{
    public UserControl View { get; protected set; }

    public LoadViewMessage(UserControl view, object sender): base(sender)
    {
        View = view;
    }

    public LoadViewMessage(UserControl view):this(view, null){}
}

PS: ObjectLocator は、オブジェクトのすべてのインスタンス化とそのライフサイクルを処理する NinJect クラスです。

@UPDATE LBugnion (MVVM Light の作成者) は、トークンを取る Send のオーバーロードを実際に使用していた send メソッドに問題があることを指摘しました。

@これは私の状況では機能しません

Messenger.Default.Send(new LoadViewMessage(ObjectLocator.MainMapView), this);

@これはうまくいく

Messenger.Default.Send(new LoadViewMessage(ObjectLocator.MainMapView, this));

これは、トークンとして Send メソッドではなく、 loadViewMessageに渡されるはずでした。

4

1 に答える 1

4

あなたの問題はSendメソッドにあります。トークンを2番目のパラメーターとして受け取るメソッドのオーバーロードを使用しています。「これ」をトークンとして渡しています。これは、(おそらく誤って)メッセージの送信者をトークンとして使用していることを意味します。

トークンを使用して送信する場合は、受信者を同じトークン(この場合、Sendメソッドで使用されるインスタンスとまったく同じインスタンス)で登録する必要もあります。トークンを登録しなかったため、メッセージがメッセンジャーによって送信されることはありません。これは最適化メカニズムです。

私の推測では、Sendメソッドでのトークンの使用法を誤解していると思います。トークンは、必要に応じて「プライベートメッセージングネットワーク」を構築する方法としてのみここにあります。この場合、2つのオブジェクトが同じトークンを使用して、プライベート通信を登録/送信および確立できます。

あなたの場合、Senderをメッセージと一緒に送信したい場合は、Senderをメッセージ自体に保存する必要があります。これはMessageBaseと派生クラスが行うことです。

お役に立てれば

ローラン

于 2012-11-13T18:07:55.047 に答える