【发布时间】:2016-10-27 10:01:06
【问题描述】:
我在这里问这个问题是因为我试图弄清楚这一点不知所措。我已经搜索过,所有出现的都是有意义的,但也不适用于我的情况。
我将WPF 与MVVM 和Caliburn.Micro 一起使用。我有一个 shell 窗口,其对应的视图模型是 Conductor<Screen>.Collection.OnceActive 和一个继承自 Screen 的屏幕。我在 Conductor 的构造函数中调用 ActivateItem 以显示后续屏幕,它正确显示屏幕,但从不调用屏幕对 OnActivate 的覆盖,并且屏幕的 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 函数并查看发生了什么。出于某种原因,当我第一次从 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 中为 false 的原因是因为我的 Conductor 是使用 DisplayRootViewFor 创建的根视图,并且看起来该函数没有将 IsActive 属性设置为 true。
那么,知道了这一点,我只是简单地实现了这个错误并且指挥者不能/不应该是根视图吗?我是否需要有第二个子视图,即指挥(这似乎有点多)?
【问题讨论】:
标签: wpf caliburn.micro