Caliburn.Micro和事件聚合器 - 不需要的调用句柄方法

时间:2010-12-25 13:03:18

标签: events caliburn.micro eventaggregator

我在2个屏幕之间发布/处理消息有一个问题。

我的情景是:

  1. Messenger屏幕,是主屏幕,在聊天屏幕上发布,它们是从屏幕。 Messenger视图模型句柄,包含来自服务器的消息。

  2. 聊天屏幕可以在信使屏幕上发布消息。而messanger视图模型在服务器上发送此消息。

  3. Messenger类看起来像这样:

     [Export("MessengerScreen", typeof(IMessengerViewModel))]
        public class MessengerViewModel : Screen, IMessengerViewModel, IInitializable<Account>, IHandle<Rp>
        {
            // ...
    
            [ImportingConstructor]
            public MessengerViewModel(IPokecService service, IEventAggregator eventAgg)
            {
                _eventAgg = eventAgg;
                _eventAgg.Subscribe(this);
            }
    
    
            //publish on slave screen 
            public void Publish(Rp rp)
            {
                _eventAgg.Publish(rp);
            }
    
            //handle msg from slave screen
            public void Handle(Rp msg)
            {
                //send to server
            }
        }
    

    Slave screen class看起来像这样:

       [Export("ChatScreen", typeof(IChatViewModel))]
        [PartCreationPolicy(CreationPolicy.NonShared)]
        public class ChatViewModel : Screen, IInitializable<DetailData>, IHandle<Rp>
        {
            [ImportingConstructor]
            public ChatViewModel(IEventAggregator eventAgg)
            {
                _eventAgg = eventAgg;
                _eventAgg.Subscribe(this);
            }
    
            //publish only on messenger screen
            public void Publish(Rp rp)
            {
                _eventAgg.Publish(rp);
            }
    
            //show message from published from messenger
            public void Handle(Rp rp)
            {
                AddBlockToConversation(rp);
            }
    
            //if enter is pressed publish on messanger screen
            public void SendRp(KeyEventArgs e)
            {
                if (e.Key == Key.Enter && !string.IsNullOrEmpty(RpText))
                {
                    _yourRp.Time = String.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now);
    
                    _yourRp.RpText = RpText;
    
                    AddBlockToConversation(_yourRp);
    
    
                    //publish on messanger screen
                    Publish(_yourRp);
                }
            }
        }
    

    我的问题是:

    第一个问题是:

    • 我从类中调用方法SendRp ChatViewModel。
    • 它在ChatViewModel中调用方法void Publish(),
    • 然后是来自MessengerViewModel类的调用方法void Handle()
    • 然后调用方法void 来自ChatViewModel类的Handle()。

    我不想在ChatViewModel类中调用方法Handle()。为什么我从ChatViewModel发送消息到MessengerViewModel在ChatViewModel类中也被称为方法句柄?

    我的第二个问题是:

    我想在某个从属屏幕上发布MessengerViewModel消息。

    MessgerVieModel有队列消息:{msg1,msg2,msg3,...,msgN}

    我想发布:

      从属屏幕#1上的
    • msg1。
    • 从属屏幕上的
    • msg2#2
    • ...
    • 从属屏幕#3 上的
    • msg3

1 个答案:

答案 0 :(得分:2)

我的解决方案: 我用修改类EventAggregator解决了我的问题。

这样的事情:

我的每个视图模型都会影响这个界面:

public interface  IViewModelIdentity
{
    string ScreenIdentity { get; set; }
}

在甚至聚合器类的Publish方法中,我有这个:

 public void Publish(Rp rp)
        {

            WeakReference[] toNotify;
            lock (_subscribers)
                toNotify = _subscribers.ToArray();

            Execute.OnUIThread(() =>
            {
                Log.Info("Publishing {0}.", rp);
                var dead = new List<WeakReference>();

                foreach (var reference in toNotify)
                {
                    var target = reference.Target as IHandle<Rp>;

                    //GET ID OF SCREEN
                    var screenId = reference.Target as IViewModelIdentity;

                    //!
                    if (target != null && screenId != null)
                    {
                        if (screenId.ScreenIdentity=="screen on which we want to send a message")
                        {
                            //PUBLISH ON SCREEN
                            target.Handle(rp);
                        }
                    }
                    else if (!reference.IsAlive)
                        dead.Add(reference);
                }
                if (dead.Count > 0)
                {
                    lock (_subscribers)
                        dead.Apply(x => _subscribers.Remove(x));
                }
            });
        }