为什么不调用 OnActivate?

Why isn't OnActivate being called?

我在这里问这个问题是因为我在尝试解决这个问题时不知所措。我已经搜索过了,所有出现的都是有意义的,但也不适用我的情况。

我将 WPFMVVMCaliburn.Micro 一起使用。我有一个 shell window 和一个相应的视图模型,它是一个 Conductor<Screen>.Collection.OnceActive 和一个继承自 Screen 的屏幕。我在 Conductor 的构造函数中调用 ActivateItem 以显示后续屏幕,它正确显示了屏幕,但从不调用 OnActivate 的屏幕覆盖,屏幕的 IsActive 属性 是设置为 False.

这只会在我第一次从 Conductor 调用 ActivateItem 时发生,所有其他调用都会正确调用 OnActivateOnDeactivate

这对我来说毫无意义,我不知道发生了什么。我清理了解决方案,重建,甚至重新启动,但它仍然无法正常工作。下面是代码:

母导体

[Export]
public sealed class ShellViewModel : Conductor<Screen>.Collection.OneActive, IHandle<SimpleMessage>
{
    private readonly DashboardViewModel m_Dash;
    private readonly LoginViewModel m_Login;
    private readonly IEventAggregator m_MsgBus;

    [ImportingConstructor]
    public ShellViewModel(DashboardViewModel dash, LoginViewModel login, IEventAggregator msgBus)
    {
        this.m_MsgBus = msgBus;
        this.m_Dash = dash;
        this.m_Login = login;

        this.ActivateItem(this.m_Login);
    }

    protected override void OnActivate()
    {
        this.m_MsgBus.Subscribe(this); //called correctly
    }

    protected override void OnDeactivate(bool close)
    {
        this.m_MsgBus.Unsubscribe(this); //called correctly
    }

    public void Handle(SimpleMessage message)
    {
        switch (message)
        {
            case SimpleMessage.LoginSuccess:
                this.ActivateItem(this.m_Dash);
                break;

            case SimpleMessage.Logout:
                this.ActivateItem(this.m_Login);
                break;
        }
    }
}

子屏幕

[Export]
public sealed class LoginViewModel : Screen
{
    private readonly IEventAggregator m_MsgBus;

    [ImportingConstructor]
    public LoginViewModel(IEventAggregator msgBus)
    {
        this.m_MsgBus = msgBus;
    }

    protected override void OnActivate()
    {
        //NOT called the first time, but is called every other time
        MessageBox.Show("ACTIVATE TEST");
    }

    protected override void OnDeactivate(bool close)
    {
        //NOT called the first time, but is called every other time
        MessageBox.Show("DEACTIVATE TEST");
    }

    public void CmdLogin(string password)
    {
        this.m_MsgBus.PublishOnUIThread(SimpleMessage.LoginSuccess);
    }

    public string Username { get; set; }

    public string Password { get; set; }
}

更新

我下载了 Caliburn Micro 源代码,这样我就可以进入 ActivateItem 函数并查看发生了什么。出于某种原因,当我第一次从 Conductor 调用 ActivateItem 时,Conductor 的 IsActive 属性 设置为 false,这导致 Caliburn 跳过调用 OnActivate 覆盖。我不知道为什么 属性 会是假的。

ConductorBaseWithActiveItem.cs

protected virtual void ChangeActiveItem(T newItem, bool closePrevious) {
    ScreenExtensions.TryDeactivate(activeItem, closePrevious);

    newItem = EnsureItem(newItem);

    //Problem is here, IsActive is false the first time around in the conductor
    if(IsActive)
        ScreenExtensions.TryActivate(newItem);

    activeItem = newItem;
    NotifyOfPropertyChange("ActiveItem");
    OnActivationProcessed(activeItem, true);
}

看起来 IsActive 在 Conductor 中为假的原因是因为我的 Conductor 是使用 DisplayRootViewFor 创建的根视图并且看起来该函数没有设置 IsActive 属性 为真。

所以,知道这一点后,我是不是只是实施错误,而 Conductor 不能成为根视图?t/shouldn我需要有一个 2nd child view 是 conductor(这看起来有点多)?

我想通了,基本上是我没有想到。在 conductor/root 视图的构造函数中激活视图无法正常工作,因为它尚未被激活。 IsActive 在指挥者s/root 视图的 OnActivate 被调用之前不会设置为真。

这在某些时候可能会出现问题,因为即使在调用 OnInitialize 时导体也没有激活,这意味着是一次性初始化函数,并且 OnActivate 可以被调用多次.在我的例子中它会很好,因为我的指挥是根视图所以 OnActivate 只会被调用一次。

故事的寓意是,当导体是根视图时,不要在导体的构造函数中调用 ActivateItem