Mvvm Light Messenger消息从未收到过

时间:2012-11-12 21:34:03

标签: silverlight mvvm-light messaging

我有一个奇怪的问题。

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

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

此类不是ViewModel,因此不会从ViewModelBase继承。

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

我尝试了以下内容:

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

    看起来像一个视图模型必须在信使工作之前“链接”到一个视图,但是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类,它处理对象及其生命周期的所有实例化

    @UPDATE LBugnion(MVVM Light的创建者)指出问题在于send方法,其中我实际上使用了一个带有令牌的Send的重载。

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

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

    @This WILL work

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

    应该传递给 loadViewMessage 而不是传递方法作为令牌

1 个答案:

答案 0 :(得分:4)

您的问题出在Send方法上。您正在使用将令牌作为第二个参数的方法的重载。你传递“this”作为标记。这意味着您(可能是错误的)使用邮件的发件人作为令牌。

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

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

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

希望这有帮助

劳伦