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

发布于 2024-10-09 11:24:45 字数 2720 浏览 6 评论 0原文

我在两个屏幕之间发布/处理消息时遇到一个问题。

我的场景是:

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

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

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
        }
    }

从属屏幕类如下所示:

   [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 中的 void Publish() 方法,
  • 然后调用 MessengerViewModel 类中的 void Handle() 方法
  • ,然后还调用 void 方法 ChatViewModel 类中的 Handle() 。

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

我的第二个问题是:

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

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

我想

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

I have one problem with publish/handle messages between 2 screens.

My scenario is:

  1. Messenger screen, is it master screen, publish on chat screens, they are slave screens.
    Messenger view model handle with messages from server.

  2. Chat screen can publishes messages on messenger screen. And messanger view model send this message on server.

Messenger class look like this:

 [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 look like this:

   [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);
            }
        }
    }

My problems are:

First problem is:

  • I call method SendRp from class
    ChatViewModel.
  • It calls method void Publish() in ChatViewModel,
  • then is call method void Handle() from class MessengerViewModel
  • and then call also method void
    Handle() from ChatViewModel class.

I don’t want call method Handle() in ChatViewModel class. Why if I send message from ChatViewModel to MessengerViewModel is also called method Handle in ChatViewModel class?

My second problem is:

I would like publish from MessengerViewModel message on only certain slave screen.

MessgerVieModel have in queue messages: {msg1, msg2, msg3, ..., msgN}

I would like publish:

  • msg1 on slave screen #1.
  • msg2 on slave screen #2
  • ...
  • msg3 on slave screen #3

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

会发光的星星闪亮亮i 2024-10-16 11:24:45

我的解决方案:
我通过修改类 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));
                }
            });
        }

MY SOLUTION:
I solved my problem with modification class EventAggregator.

Something like this:

Every my view model imlements this interface:

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

And in Publish method in even aggregator class I have this:

 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));
                }
            });
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文