【问题标题】:Why is Caliburn.Micro's (used with modern-ui) OnActivate not being called after ActivateItem?为什么在 ActivateItem 之后没有调用 Caliburn.Micro 的(与现代 UI 一起使用)OnActivate?
【发布时间】:2014-10-07 16:53:47
【问题描述】:

我在WPF 应用程序中使用Caliburn.MicroModern-UI。在modern-ui 框架(即UserControl)内的“页面”上,我试图使用Conductor 来切换当前视图。这是我到目前为止所得到的:

注意:为简洁起见,从源中删除了命名空间

现代 UI 窗口中“页面”的 XAML

<UserControl x:Class="ShellView">
    <ContentControl x:Name="ActiveItem" />
</UserControl>

ShellViewModel 的来源(指挥者)

[Export]
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
{
    private readonly Test1ViewModel m_TestView1;
    private readonly Test2ViewModel m_TestView2;

    public ShellViewModel()
    {
        this.m_TestView1 = new Test1ViewModel();
        this.m_TestView2 = new Test2ViewModel();

        this.ActivateItem(this.m_TestView1);
    }
}

Test1View 的 XAML 目前没有任何内容,只是普通的 UserControl 内容。

Test1ViewModel 的来源

public class Test1ViewModel : Screen
{
    protected override void OnActivate()
    {
        //This DOES NOT show or fire, I even put a breakpoint to double check
        Debug.Print("This should show in output");
    }
}

ActivateItem 被调用时,OnActivate 根本不会触发。我什至尝试在指挥中的视图模型Test1ViewModel 上调用ConductWith(this),但这没有用。我正在使用Modern-UI,这可能很重要,因为这同样适用于不使用Modern-UI 的不同项目。哦,当ActivateItem 被调用时,屏幕上会显示相应的视图(我添加了一些按钮来验证视图是否发生了变化)。

关于为什么在调用ActivateItemUserControl 会显示在ContentControl 中但OnActivate 根本不会触发的任何想法?

还有一件事......这可能也与它有关,但如果是这样,我不知道为什么或如何解决它。我正在使用这个类来使视图优先Modern-UICaliburn.Micro 的模型优先方法一起工作。

internal class ModernContentLoader : DefaultContentLoader
{
    protected override object LoadContent(Uri uri)
    {
        object content = base.LoadContent(uri);
        if (content == null)
            return null;

        // Locate the right viewmodel for this view
        object vm = ViewModelLocator.LocateForView(content);
        if (vm == null)
            return content;

        // Bind it up with CM magic
        if (content is DependencyObject)
            ViewModelBinder.Bind(vm, content as DependencyObject, null);

        return content;
    }
}

【问题讨论】:

    标签: wpf caliburn.micro modern-ui


    【解决方案1】:

    我去下载了Caliburn.Micro 的源代码并调试了整个事情,就像我从一开始就应该做的那样。

    事实证明,由于Modern-UI 处理导航的方式,Conductor(除非它是附加到主窗口的主 shell 视图)不会被激活。换句话说,它永远不知道它正在被显示,并且 Caliburn 的源会检查以确保 Conductor 在允许激活新视图之前处于活动状态。由于某种原因,视图显示得很好,但View Model (Screen) 永远不会被激活或实例化。在我的例子中,它被实例化是因为 Modern-UI+Caliburn.Micro 视图绑定黑客。

    我确实让它终于工作了,所以如果有人感兴趣,这是如何让 ActivateItemConductorModern-UI 中工作。

    将以下代码行添加到您的 Conductor 的构造函数或 Modern-UI 方法 OnNavigatedTo

    ScreenExtensions.TryActivate(this);
    

    这是Caliburn-Micro 的一部分,将允许您的Conductor 正确激活项目。如果您在 OnNavigatedTo 中使用它,您可能需要将此行添加到您的 OnNavigatedFrom 方法中:

    ScreenExtensions.TryDeactivate(this, true);
    

    【讨论】:

    • 我遇到了类似的问题。我需要通过从对象引用调用 ActivateItem 来切换视图。示例:假设一个选项卡式界面,其中 viewmodel aaa 当前处于活动状态,而 viewmodel ccc 已停用。以下代码写在 viewmodel aaa 中的一个方法中:ViewModelB bbb = new ViewModelB();ccc.ActivateItem(bbb); 但是如果我切换回未加载 bbb 的 ccc。我该如何克服这个问题?
    • @Rahul 虽然看起来很相似,但我认为您的问题与我原来的问题完全不同。我建议创建一个新问题,以便您可以更好地描述您的问题并提供更深入的代码示例。
    • 非常感谢@vane-感谢您为我调试-您的解决方案绝对正确,我遇到了同样的问题,没有明显原因我的项目没有激活(OnActivated 事件),事实证明,当我放置一个衬垫ScreenExtensions.TryActivate(this); 时,父导体本身并没有被激活,一切都在正常工作(正常情况下)。我不确定是否需要“停用”(就像您提到的那样),因为我真的不需要。再次感谢伙计!
    猜你喜欢
    • 2015-06-04
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 2012-02-24
    相关资源
    最近更新 更多