为什么没有OnActivate被调用?

时间:2016-06-24 17:40:59

标签: wpf caliburn.micro

我在这里问这个问题是因为我试图解决这个问题而感到茫然。我搜索过,所有出现的内容都是有意义的,但也不适用于我的情况。

我在WPFMVVM使用Caliburn.Micro。我有一个shell窗口,其中包含一个Conductor<Screen>.Collection.OnceActive的相应视图模型和一个继承自Screen的屏幕。我在指挥家的构造函数中调用ActivateItem来显示后续屏幕,它正确显示屏幕,但从未调用屏幕覆盖OnActivate和屏幕&# 39; s IsActive属性设置为False

这仅在我第一次从指挥致电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功能,看看发生了什么。出于某种原因,当我第一次从指挥家呼叫ActivateItem时,指挥的IsActive属性设置为假,这导致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为假的原因是因为我的指挥是使用DisplayRootViewFor创建的根视图,看起来该函数未设置IsActive财产到真。

所以,知道这一点,我只是实施了这个错误而且指挥家不能/不应该是根视图吗?我是否需要第二个孩子视图,这是指挥(看起来有点多)?

1 个答案:

答案 0 :(得分:3)

我想通了,基本上我没想到。激活导体/根视图的构造函数中的视图不能正常工作,因为它尚未激活。在调用指挥家/根视图IsActive之前,OnActivate未设置为true。

这在某些时候可能会有问题,因为即使调用OnInitialize导体也没有活动,这意味着一次初始化函数,OnActivate可以被多次调用。在我的情况下它会很好,因为我的指挥是根视图所以OnActivate只会被调用一次。

故事的道德是,当指挥是根视图时,不要在指挥的构造函数中调用ActivateItem