Caliburn.Micro- und Ereignisaggregator -Unschwärte Call -Handle -Methode
-
13-10-2019 - |
Frage
Ich habe ein Problem mit der Veröffentlichung/Handlungsnachrichten zwischen 2 Bildschirmen.
Mein Szenario ist:
Messenger -Bildschirm, ist It Master -Bildschirm, veröffentlicht auf Chat -Bildschirmen, sie sind Sklavenbildschirme. Messenger -View -Modellhandle mit Nachrichten vom Server.
Der Chat -Bildschirm kann Nachrichten auf dem Messenger -Bildschirm veröffentlichen. Und Messanger View -Modell senden diese Nachricht auf dem Server.
Messenger -Klasse sehen so aus:
[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
}
}
Sklavenbildschirmklasse sehen so aus:
[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);
}
}
}
Meine Probleme sind:
Das erste Problem ist:
- Ich rufe methode sendRP von Class ChatviewModel auf.
- Es nennt die Methode void Publish () in ChatviewModel,
- Dann ist die Call -Methode void Handle () von Class MessengerViewModel
- und rufen Sie dann auch Methode void Handle () von der ChatViewModel -Klasse auf.
Ich möchte keine Call -Methode Handle () in der ChatviewModel -Klasse. Warum, wenn ich eine Nachricht von ChatviewModel an MessengerViewModel sende, wird auch in der ChatviewModel -Klasse als Methode -Handle bezeichnet?
Mein zweites Problem ist:
Ich möchte von MessengerViewModel -Nachricht nur auf einem bestimmten Sklavenbildschirm veröffentlichen.
Messgerviemodel haben in Warteschlangennachrichten: {Msg1, Msg2, Msg3, ..., Msgn}
Ich möchte veröffentlichen:
- MSG1 auf Slave -Bildschirm Nr. 1.
- MSG2 auf Slave -Bildschirm Nr. 2
- ...
- MSG3 auf Slave -Bildschirm #3
Lösung
Meine Lösung: Ich habe mein Problem mit der Änderungsklasse EventAggregator gelöst.
Etwas wie das:
Jedes meine Ansichtsmodell imlementiert diese Schnittstelle:
public interface IViewModelIdentity
{
string ScreenIdentity { get; set; }
}
Und in der Veröffentlichung der Methode auch in der Aggregator -Klasse habe ich Folgendes:
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));
}
});
}