Caliburn.Micro和事件聚合器 - 调用句柄方法 [英] Caliburn.Micro and event aggregator -unwanted call handle method

查看:230
本文介绍了Caliburn.Micro和事件聚合器 - 调用句柄方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的方案是:


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


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


Messenger类看起来像这样:

  [导出(MessengerScreen,typeof(IMessengerViewModel))] 
public class MessengerViewModel:Screen,IMessengerViewModel,IInitializable< Account> IHandle< Rp& ;
{
// ...

[ImportingConstructor]
public MessengerViewModel(IPokecService service,IEventAggregator eventAgg)
{
_eventAgg = eventAgg ;
_eventAgg.Subscribe(this);
}


//在从屏幕上发布
public void Publish(Rp rp)
{
_eventAgg.Publish(rp);
}

//从从属屏幕处理msg
public void Handle(Rp msg)
{
//发送到服务器
}
}

从屏幕类看起来像这样:


$
public class ChatViewModel:Screen, IInitializable< DetailData>,IHandle< Rp>
{
[ImportingConstructor]
public ChatViewModel(IEventAggregator eventAgg)
{
_eventAgg = eventAgg;
_eventAgg.Subscribe(this);
}

//仅在信使屏幕上发布
public void Publish(Rp rp)
{
_eventAgg.Publish(rp);
}

//显示从messenger发布的消息
public void Handle(Rp rp)
{
AddBlockToConversation(rp);
}

//如果输入被按下发布在messanger屏幕上
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 。现在);

_yourRp.RpText = RpText;

AddBlockToConversation(_yourRp);


//发布在messanger屏幕上
发布(_yourRp);
}
}
}

我的问题是: p>

第一个问题是:




  • 我调用SendRp方法从class
    ChatViewModel。

  • 它调用方法void Publish()在ChatViewModel,

  • 然后调用方法void Handle()从类MessengerViewModel

  • 然后调用方法void
    来自ChatViewModel类的Handle()。



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



我的第二个问题是:



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



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



我想发布:




  • msg1在从属屏幕#1上。

  • 从屏幕#2上的msg2

  • ...

  • msg3 on从屏幕#3


解决方案

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



这样的东西:



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

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

在甚至聚合器类的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 ==我们要发送消息的屏幕)
{
// PUBLISH ON SCREEN
target.Handle(rp );
}
}
else if(!reference.IsAlive)
dea d.Add(参考);
}
if(dead.Count> 0)
{
lock(_subscribers)
dead.Apply(x => _subscribers.Remove(x)) ;
}
});
}


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

解决方案

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

这篇关于Caliburn.Micro和事件聚合器 - 调用句柄方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆