【问题标题】:Mvvm Light Messenger message never recieved从未收到 Mvvm Light Messenger 消息
【发布时间】:2012-11-12 21:34:03
【问题描述】:

我有一个奇怪的问题。

我正在使用 GalaSoft 的 MVVM Light 框架,到目前为止一切正常。 在我尝试执行以下操作之前,我正在使用信使系统在 ViewModel 之间发送消息:

我有一个发送消息的单例类 GateKeeper

此类不是 ViewModel,因此不继承自 ViewModelBase

如果它发送一条消息,它不会在任何地方收到。

我尝试了以下方法:

  1. GateKeeper 继承自ViewModeBase -> 没有成功。
  2. 注册GateKeeper 以接收消息,从而查看它是否会捕获/接收实际从自身发送的消息 -> 不成功。
  3. GateKeeper 从 Singleton 更改为正常实例化 -> 没有成功
  4. 创建一个未连接到视图的 MVVM ViewModel,并让它发送消息,就像 GateKeeper -> no Success

我所有连接到视图的视图模型都可以发送消息,并且它们将被接收。

在信使工作之前,似乎必须将视图模型“链接”到视图,但 imo。这是一个主要限制。

以下是当前非常简化的设置。

在 GateKeeper 上调用 ApplicationInitialize 不会触发主视图模型或 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 类,用于处理对象的所有实例化及其生命周期

@更新 LBugnion(MVVM Light 的创建者)指出问题出在 send 方法上,我实际上是在使用带有令牌的 Send 重载。

@这在我的情况下不起作用

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

@这会起作用

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

this 应该作为 token

传递给 loadViewMessage 而不是 Send 方法

【问题讨论】:

  • 我不知道为什么您的代码不起作用,但我可以告诉您它应该。消息传递系统不依赖于 ViewModel/View 关系。
  • 你调试过(断点)GateKeeper 方法吗?例如,您使用的是非默认构造函数(带参数),它被调用了吗?
  • 非常。它应该可以工作,并且当我在视图中使用的其他视图模型中使用它时也可以。我已经调试了所有并调用了 GateKeeper 的构造函数。我不知道为什么它在这里不起作用。

标签: silverlight mvvm-light messaging


【解决方案1】:

您的问题出在 Send 方法上。您正在使用将令牌作为第二个参数的方法的重载。您将“this”作为令牌传递。这意味着您(可能是错误地)将消息的发送者用作令牌。

如果您使用令牌发送,您还需要使用相同的令牌注册接收方(在这种情况下,与 Send 方法中使用的实例完全相同)。由于您没有注册令牌,因此消息永远不会由 Messenger 发送,这是一种优化机制。

我的猜测是您误解了 Send 方法中令牌的用法。如果您愿意,令牌只是作为构建“私人消息传递网络”的一种方式,其中两个对象可以使用相同的令牌注册/发送并建立私人通信。

在您的情况下,如果您想将 Sender 与消息一起发送,则需要将 Sender 保存在消息本身中,这就是 MessageBase 和派生类所做的。

希望对你有帮助

劳伦特

【讨论】:

  • 哦该死..我可以看到问题!参数“this”实际上应该是我的 LoadViewMessage 的一部分,但错误地成为了 Send 重载方法的一部分,因此变成了一个令牌。非常感谢劳伦特。我会更新我的问题以反映您的答案。问候
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-14
  • 2019-05-11
  • 2016-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多