首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ViewModel不会处理EventAggregator事件

ViewModel不会处理EventAggregator事件
EN

Stack Overflow用户
提问于 2022-03-29 04:57:47
回答 1查看 95关注 0票数 0

我似乎只能处理来自ShellViewModelShellViewModel事件,但我想从LoginViewModel处理它。

ShellViewModelLoginViewModel构造为它的活动项。我还将它设置为从IHandle<AuthenticatedMessage>继承作为事件发布是否有效的测试。它能够处理那个事件。为了简洁起见,我没有在代码中显示任何取消订阅事件。

代码语言:javascript
复制
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窗口(显示在下面)。

代码语言:javascript
复制
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事件的AuthenticatedMessage

代码语言:javascript
复制
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));                              
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-29 06:14:57

在将eventAggregator.SubscribeOnPublishedThread(this);移动到LoginViewModel构造函数而不是OnActivateAsync()方法之后,我解决了这个问题。

从这里:

代码语言:javascript
复制
protected override async Task OnActivateAsync(CancellationToken cancellationToken)
{
    await base.OnActivateAsync(cancellationToken);
    
    _eventAggregator.SubscribeOnPublishedThread(this);
}

到这里:

代码语言:javascript
复制
public LoginViewModel(IEventAggregator eventAggregator, 
    IWindowManager windowManager, 
    ILoginWindowViewModelFactory loginWindowViewModelFactory)
{
    _eventAggregator = eventAggregator; 
    _windowManager = windowManager;
    _LoginWindowViewModelFactory = loginWindowViewModelFactory;

    _eventAggregator.SubscribeOnPublishedThread(this);
}

编辑:

当视图第一次在ShellViewModel中创建时,不会调用ShellViewModel方法,因为它是我的根屏幕和导体。所以订阅从来没有发生过。

代码语言:javascript
复制
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.
    }
}

它与this problem and answer直接相关。

这就解释了为什么将它移到构造函数中解决了这个问题。

最后的解决方案是在Constructor和OnActivateAsync方法中添加OnActivateAsync。这允许我重新订阅事件后,我导航离开这个视图模型,并回到它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71656679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档