caliburn.micro eventAggregator: Обработка сообщения в Screen Collection

У меня есть следующий код в моем калибровочном микро-приложении. Я использую eventAggregator для отправки сообщений из одной модели представления в другую.

Рассмотрим следующий код:

public class ShellViewModel : Conductor<IWorkspace>.Collection.OneActive, IShell
{
   ...
}

public class ViewModelA
{
   ...
}

public class ViewModelB
{
   ViewModelA messageSender{get;set};
   ...
}

Требование: мне нужно отправить сообщение из ViewModelA в ViewModelB.

Проблема: существует несколько экземпляров ViewModel, которые создаются и добавляются в коллекцию экрана. Мне нужно отправить сообщение только конкретному экземпляру ViewModelB. Все остальные экземпляры viewmodel должны игнорировать сообщение.

Примечание. В приведенном выше примере кода я отправляю сообщение из объекта viewmodel messageSender вмещающий класс. Поэтому сообщение следует отправлять только экземпляру родительского объекта.

Вопрос

  1. Есть ли какая-либо встроенная функциональность, доступная в caliburn micro framework, чтобы справиться с этой ситуацией?
  2. Если нет, то есть ли метод уникальной идентификации экземпляра viewmodel для обработки сообщения?

3 ответа

Я не думаю, что в Caliburn EventAggregator это встроено. PRISM EventAggregator позволяет передавать функцию фильтра, а MVVMLight Messenger использует объект токена.

Я думаю, в Caliburn вам нужно было бы включить что-то в сообщение, чтобы подписчики могли решить, обрабатывать ли они сообщение или нет.

IHandle<T> используется в классе, который должен "действовать" на сообщение, которое вы публикуете с помощью IEventAggregator, обычно в качестве инъекции. не забывайте подписываться и отписываться в соответствии с Активировать и деактивировать, когда он либо становится неактивным, либо закрывается. Только тот класс, который наследует IHandle<T> с его "уникальной" подписью откликнется на трансляцию. Теперь, конечно, если вы несколько IHandle<string>Например, все виртуальные машины будут пытаться обработать отправленное сообщение, если они были подключены для этого.

//Handle<T> for any built-in type or something you create like MessageEvent etc.
public class ViewModelB : Screen, IHandle<string>   
{
   public ViewModelB(IEventAggregator events){
      _event = events;
      _events.Subscribe(this);
   }

   private void Handle(string t){
      MessageBox.Show(t);
   }
}

public class ViewModelA : Screen
{
    private readonly IEventAggregator _event;

    public ViewModelA(IEventAggregator events)
    {
        _event = events;
        _event.Subscribe(this);
    }

    public void SomethingWasClicked()
    {
         _event.PublishOnUIThread("Hello, World!");
     }
}

Чтобы уточнить, что сказал mvermef, вам необходимо реализовать IHandle<T> интерфейс в моделях представления, которые будут обрабатывать определенные сообщения. Так как он выбрал string для типа сообщения, вам придется проанализировать сообщение в ViewModelB чтобы справиться с этим, если другие модели представления реализовали IHandle<string> интерфейс. Возвращаясь к вашему примеру и сделав его более конкретным для ViewModelB, вы можете наследовать от базового класса, который обрабатывает сообщения на основе строк.

public class StringMessageEventBase
{    
    private string _Message;
    public StringMessageEventBase()
        : this(null) { }

    public StringMessageEventBase(string message)
    {
        _Message = message;
    }

    public string Message
    {
        get { return _Profile; }
        set { _Profile = value; }
    }
}

public class ViewModelBMessageEvent : StringMessageEventBase
{
    public ViewModelBMessageEvent(string message)
        : base(profile) {}
}

Теперь, если вы реализуете IHandle<ViewModelBMessageEvent> по вашему мнению модель, ViewModelB, тогда только случаи ViewModelB обработает сообщение.

public class ViewModelB : IHandle<ViewModelBMessageEvent>
{
    private readonly IEventAggregator _Aggregator;

    public ViewModelB(IEventAggregator aggregator)
    {
        if (aggregator == null)
            throw new ArgumentNullException("aggregator");
        _Aggregator = aggregator;
        _Aggregator.Subscribe(this);
    }

    public void Handle(ViewModelBMessageEvent message)
    { 
        // do some thing with your message here
        var msg = message.Message;
    }
}
Другие вопросы по тегам