ViewModel赢得了EventAggregator事件的处理
我似乎只能从 ShellViewModel
处理 EventAggregator 事件,但我想从 LoginViewModel
处理它。
ShellViewModel
构造 LoginViewModel
作为活动项。我还将其设置为从 IHandle
继承,作为事件发布是否正常工作的测试。它能够处理该事件。为了简洁起见,我没有在代码中显示任何取消订阅事件。
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<AuthenticatedMessage>
{
public ShellViewModel(IEventAggregator eventAggregator, LoginViewModel loginViewModel)
{
_eventAggregator = eventAggregator;
_loginViewModel = loginViewModel;
}
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
_eventAggregator.SubscribeOnPublishedThread(this);
await ActivateItemAsync(_loginViewModel);
}
public async Task HandleAsync(AuthenticatedMessage authCode, CancellationToken cancellationToken)
{
// this is reached! So the event is publishing successfully.
await Task.CompletedTask;
}
}
LoginViewModel
也订阅了这个事件,但它的 Handle 方法没有被调用。
Login
方法负责创建发布事件的 LoginWindowViewModel
窗口(如下所示)。
public class LoginViewModel : Screen, IHandle<AuthenticatedMessage>
{
private IEventAggregator _eventAggregator;
private readonly IWindowManager _windowManager;
private readonly ILoginWindowViewModelFactory _LoginWindowViewModelFactory;
public LoginViewModel(IEventAggregator eventAggregator,
IWindowManager windowManager,
ILoginWindowViewModelFactory loginWindowViewModelFactory)
{
_eventAggregator = eventAggregator;
_windowManager = windowManager;
_LoginWindowViewModelFactory = loginWindowViewModelFactory;
}
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
_eventAggregator.SubscribeOnPublishedThread(this);
}
// This is bound to a button click event. It creates a window.
public async void Login()
{
Uri loginUri = new Uri(_api.BaseLoginUrl);
await _windowManager.ShowWindowAsync(
_ndLoginWindowViewModelFactory.Create(loginUri, _eventAggregator));
}
public async Task HandleAsync(AuthenticatedMessage authCode, CancellationToken cancellationToken)
{
// why is this is never reached?
await Task.CompletedTask;
}
}
发布 AuthenticatedMessage
事件的 LoginWindowViewModel
:
public class LoginWindowViewModel : Screen
{
private readonly IEventAggregator _eventAggregator;
private readonly Uri _initialUri;
public NDLoginWindowViewModel(Uri initialUri, IEventAggregator eventAggregator)
{
_initialUri = initialUri;
_eventAggregator = eventAggregator;
}
// bound to the WebView2 (browser control) event
public async void NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
string authCode = HttpUtility.ParseQueryString(new Uri(e.Uri).Query).Get("code");
// Publish event here. LoginViewModel should handle this, but currently only ShellViewModel can.
await _eventAggregator.PublishOnUIThreadAsync(new AuthenticatedMessage(authCode));
}
}
}
I only seem to be able to handle EventAggregator events from the ShellViewModel
, but I want to handle it from LoginViewModel
.
The ShellViewModel
constructs LoginViewModel
as it's Active Item. I've also set it up to inherit from IHandle<AuthenticatedMessage>
as a test that event publishing is working. It is able to handle that event. I haven't shown any Unsubscribe events in my code for brevity.
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<AuthenticatedMessage>
{
public ShellViewModel(IEventAggregator eventAggregator, LoginViewModel loginViewModel)
{
_eventAggregator = eventAggregator;
_loginViewModel = loginViewModel;
}
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
_eventAggregator.SubscribeOnPublishedThread(this);
await ActivateItemAsync(_loginViewModel);
}
public async Task HandleAsync(AuthenticatedMessage authCode, CancellationToken cancellationToken)
{
// this is reached! So the event is publishing successfully.
await Task.CompletedTask;
}
}
LoginViewModel
also subscribes to this event, but it's Handle method is not invoked.
The Login
method is responsible for creating the LoginWindowViewModel
Window (shown underneath) which publishes the event.
public class LoginViewModel : Screen, IHandle<AuthenticatedMessage>
{
private IEventAggregator _eventAggregator;
private readonly IWindowManager _windowManager;
private readonly ILoginWindowViewModelFactory _LoginWindowViewModelFactory;
public LoginViewModel(IEventAggregator eventAggregator,
IWindowManager windowManager,
ILoginWindowViewModelFactory loginWindowViewModelFactory)
{
_eventAggregator = eventAggregator;
_windowManager = windowManager;
_LoginWindowViewModelFactory = loginWindowViewModelFactory;
}
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
_eventAggregator.SubscribeOnPublishedThread(this);
}
// This is bound to a button click event. It creates a window.
public async void Login()
{
Uri loginUri = new Uri(_api.BaseLoginUrl);
await _windowManager.ShowWindowAsync(
_ndLoginWindowViewModelFactory.Create(loginUri, _eventAggregator));
}
public async Task HandleAsync(AuthenticatedMessage authCode, CancellationToken cancellationToken)
{
// why is this is never reached?
await Task.CompletedTask;
}
}
The LoginWindowViewModel
that publishes a AuthenticatedMessage
event:
public class LoginWindowViewModel : Screen
{
private readonly IEventAggregator _eventAggregator;
private readonly Uri _initialUri;
public NDLoginWindowViewModel(Uri initialUri, IEventAggregator eventAggregator)
{
_initialUri = initialUri;
_eventAggregator = eventAggregator;
}
// bound to the WebView2 (browser control) event
public async void NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
string authCode = HttpUtility.ParseQueryString(new Uri(e.Uri).Query).Get("code");
// Publish event here. LoginViewModel should handle this, but currently only ShellViewModel can.
await _eventAggregator.PublishOnUIThreadAsync(new AuthenticatedMessage(authCode));
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我在移动
eventAggregator.subscribeoneparperemendthread(this);
loginViewModel 构造器之后解决了问题,而不是loginViewModel
sonstructor,而不是onactivateasync()
method。从这里:
到这里:
编辑:
onactivateasync
方法在首次在shellViewModel
中首次创建时未调用方法,因为它是我的根屏幕和导体。因此,订阅从未进行过。它与这个问题和答案。
这解释了为什么将其移至构造函数解决问题。
最终的解决方案是在构造函数和 onactivateasync 方法中添加
_EVENTAGGREGATOR.SUBSCRIBENENPUBLINGENREDTHREAD(this);
。这使我可以在我远离此ViewModel并回到它之后重新订阅该事件。I resolved the issue after moving
eventAggregator.SubscribeOnPublishedThread(this);
to theLoginViewModel
constructor, instead of theOnActivateAsync()
method.From here:
To here:
EDIT:
The
OnActivateAsync
method isn't being called when the View is first created in theShellViewModel
because it is my root Screen and Conductor. So the Subscription was never taking place.It is directly related to this problem and answer.
That explains why moving it to the constructor solved the problem.
The final solution was to add
_eventAggregator.SubscribeOnPublishedThread(this);
in both the Constructor ANDOnActivateAsync
method. This allows me to resubscribe to the event after I navigate away from this viewmodel and come back to it.