我在这里问这个问题是因为我试图解决这个问题而感到茫然。我搜索过,所有出现的内容都是有意义的,但也不适用于我的情况。
我在WPF
和MVVM
使用Caliburn.Micro
。我有一个shell窗口,其中包含一个Conductor<Screen>.Collection.OnceActive
的相应视图模型和一个继承自Screen
的屏幕。我在指挥家的构造函数中调用ActivateItem
来显示后续屏幕,它正确显示屏幕,但从未调用屏幕覆盖OnActivate
和屏幕&# 39; s IsActive
属性设置为False
。
这仅在我第一次从指挥致电ActivateItem
时发生,所有其他来电将正确拨打OnActivate
和OnDeactivate
。
这对我没有意义,我不知道发生了什么。我清理了解决方案,重建,甚至重新启动但它仍然无法正常工作。以下是代码:
家长指挥
[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
财产到真。
所以,知道这一点,我只是实施了这个错误而且指挥家不能/不应该是根视图吗?我是否需要第二个孩子视图,这是指挥(看起来有点多)?
答案 0 :(得分:3)
我想通了,基本上我没想到。激活导体/根视图的构造函数中的视图不能正常工作,因为它尚未激活。在调用指挥家/根视图IsActive
之前,OnActivate
未设置为true。
这在某些时候可能会有问题,因为即使调用OnInitialize
导体也没有活动,这意味着一次初始化函数,OnActivate
可以被多次调用。在我的情况下它会很好,因为我的指挥是根视图所以OnActivate
只会被调用一次。
故事的道德是,当指挥是根视图时,不要在指挥的构造函数中调用ActivateItem
。