ViewModel 不会处理 EventAggregator 事件
ViewModel won't handle a EventAggregator event
我似乎只能处理来自 ShellViewModel
的 EventAggregator 事件,但我想处理来自 LoginViewModel
的事件。
ShellViewModel
构造 LoginViewModel
因为它是活动项。我还将其设置为从 IHandle<AuthenticatedMessage>
继承,以测试事件发布是否正常。它能够处理该事件。为简洁起见,我没有在我的代码中显示任何取消订阅事件。
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
Window(如下所示)。
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));
}
}
}
我将 eventAggregator.SubscribeOnPublishedThread(this);
移动到 LoginViewModel
构造函数而不是 OnActivateAsync()
方法后解决了这个问题。
从这里开始:
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
_eventAggregator.SubscribeOnPublishedThread(this);
}
到这里:
public LoginViewModel(IEventAggregator eventAggregator,
IWindowManager windowManager,
ILoginWindowViewModelFactory loginWindowViewModelFactory)
{
_eventAggregator = eventAggregator;
_windowManager = windowManager;
_LoginWindowViewModelFactory = loginWindowViewModelFactory;
_eventAggregator.SubscribeOnPublishedThread(this);
}
编辑:
首次在 ShellViewModel
中创建视图时未调用 OnActivateAsync
方法,因为它是我的根屏幕和导体。所以订阅从未发生。
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
{
...
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
await ActivateItemAsync(_loginViewModel);
// IsActive = false here, therefore the child Screen `_loginViewModel`
// is also not active. Result is that OnActivateAsync
// in this view model does not get called.
}
}
与直接相关。
这解释了为什么将其移至构造函数解决了问题。
最终的解决方案是在 Constructor 和 OnActivateAsync
方法中添加 _eventAggregator.SubscribeOnPublishedThread(this);
。这允许我在离开此视图模型并返回后重新订阅事件。
我似乎只能处理来自 ShellViewModel
的 EventAggregator 事件,但我想处理来自 LoginViewModel
的事件。
ShellViewModel
构造 LoginViewModel
因为它是活动项。我还将其设置为从 IHandle<AuthenticatedMessage>
继承,以测试事件发布是否正常。它能够处理该事件。为简洁起见,我没有在我的代码中显示任何取消订阅事件。
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
Window(如下所示)。
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));
}
}
}
我将 eventAggregator.SubscribeOnPublishedThread(this);
移动到 LoginViewModel
构造函数而不是 OnActivateAsync()
方法后解决了这个问题。
从这里开始:
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
_eventAggregator.SubscribeOnPublishedThread(this);
}
到这里:
public LoginViewModel(IEventAggregator eventAggregator,
IWindowManager windowManager,
ILoginWindowViewModelFactory loginWindowViewModelFactory)
{
_eventAggregator = eventAggregator;
_windowManager = windowManager;
_LoginWindowViewModelFactory = loginWindowViewModelFactory;
_eventAggregator.SubscribeOnPublishedThread(this);
}
编辑:
首次在 ShellViewModel
中创建视图时未调用 OnActivateAsync
方法,因为它是我的根屏幕和导体。所以订阅从未发生。
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
{
...
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
await ActivateItemAsync(_loginViewModel);
// IsActive = false here, therefore the child Screen `_loginViewModel`
// is also not active. Result is that OnActivateAsync
// in this view model does not get called.
}
}
与
这解释了为什么将其移至构造函数解决了问题。
最终的解决方案是在 Constructor 和 OnActivateAsync
方法中添加 _eventAggregator.SubscribeOnPublishedThread(this);
。这允许我在离开此视图模型并返回后重新订阅事件。