为什么不调用 OnActivate?
Why isn't OnActivate being called?
我在这里问这个问题是因为我在尝试解决这个问题时不知所措。我已经搜索过了,所有出现的都是有意义的,但也不适用我的情况。
我将 WPF
与 MVVM
和 Caliburn.Micro
一起使用。我有一个 shell window 和一个相应的视图模型,它是一个 Conductor<Screen>.Collection.OnceActive
和一个继承自 Screen
的屏幕。我在 Conductor 的构造函数中调用 ActivateItem
以显示后续屏幕,它正确显示了屏幕,但从不调用 OnActivate
的屏幕覆盖,屏幕的 IsActive
属性 是设置为 False
.
这只会在我第一次从 Conductor 调用 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
函数并查看发生了什么。出于某种原因,当我第一次从 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
。
我在这里问这个问题是因为我在尝试解决这个问题时不知所措。我已经搜索过了,所有出现的都是有意义的,但也不适用我的情况。
我将 WPF
与 MVVM
和 Caliburn.Micro
一起使用。我有一个 shell window 和一个相应的视图模型,它是一个 Conductor<Screen>.Collection.OnceActive
和一个继承自 Screen
的屏幕。我在 Conductor 的构造函数中调用 ActivateItem
以显示后续屏幕,它正确显示了屏幕,但从不调用 OnActivate
的屏幕覆盖,屏幕的 IsActive
属性 是设置为 False
.
这只会在我第一次从 Conductor 调用 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
函数并查看发生了什么。出于某种原因,当我第一次从 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
。