简体   繁体   English

从另一个ViewModel设置Caliburn.Micro ControlContent

[英]Setting Caliburn.Micro ControlContent from another ViewModel

I'm new to Caliburn.Micro (and MVVM for that matter) and I'm trying to Activate a screen with my conductor located in ShellViewModel from a button within a sub-viewmodel (one called by the conductor). 我是Caliburn.Micro (和MVVM)的新手,我试图通过子视图模型(由导体调用)中的按钮激活位于ShellViewModel导体的屏幕。 All the tutorials I've seen have buttons in the actual shell that toggle between so I'm a little lost. 我看过的所有教程在实际的shell中都有可以在它们之间切换的按钮,所以我有点迷茫。

All the ViewModels share the namespace SafetyTraining.ViewModels 所有ViewModel共享命名空间SafetyTraining.ViewModels

The ShellViewModel (first time ever using a shell so I might be using it in the wrong manner) ShellViewModel (第一次使用外壳,所以我可能以错误的方式使用它)

public class ShellViewModel : Conductor<object>.Collection.OneActive, IHaveDisplayName
{        
    public ShellViewModel()
    {
        ShowMainView();
    }

    public void ShowMainView()
    {
        ActivateItem(new MainViewModel());
    }
}

ShellView XAML ShellView XAML

<UserControl x:Class="SafetyTraining.Views.ShellView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel>
    <ContentControl x:Name="ActiveItem" />
</DockPanel>

MainViewModel - the main screen (does correctly display). MainViewModel主屏幕(正确显示)。

public class MainViewModel : Screen
{
    public void ShowLoginPrompt()
    {
        LoginPromptViewModel lg = new LoginPromptViewModel();//This does happen
    }
}

MainView XAML MainView XAML

<Button cal:Message.Attach="[Event Click] = [ShowLoginPrompt]">Login</Button> 

LoginPromptViewModel

public class LoginPromptViewModel : Screen
{
    protected override void OnActivate()
    {
        base.OnActivate();
        MessageBox.Show("Hi");//This is for testing - currently doesn't display
    }
}

EDIT Working Code: 编辑工作代码:

Modified Sniffer's code a bit to properly fit my structure. 修改了Sniffer的代码以适合我的结构。 Thanks :) 谢谢 :)

var parentConductor = (Conductor<object>.Collection.OneActive)(this.Parent);
        parentConductor.ActivateItem(new LoginPromptViewModel());

You are doing everything correctly, but you are missing one thing though: 您可以正确地进行所有操作,但是却缺少一件事:

public void ShowLoginPrompt()
{
    LoginPromptViewModel lg = new LoginPromptViewModel();//This does happen
}

You are creating an instance of LoginPromptViewModel , but you are not telling the conductor to activate this instance, so it's OnActivate() method is never called. 您正在创建LoginPromptViewModel的实例,但是没有告诉导体激活该实例,因此永远不会调用它的OnActivate()方法。

Now before I give you a solution I should suggest a couple of things: 现在,在我为您提供解决方案之前,我应该提出几点建议:

  1. If you are using the MainViewModel to navigate between different view-models then it would be appropriate to make MainViewModel a conductor itself. 如果要使用MainViewModel在不同的视图模型之间导航,那么将MainViewModel为导体本身是合适的。

  2. If you aren't using it like that, then perhaps you should put the button that navigates to the LoginPromptViewModel in the ShellView itself. 如果您没有那样使用它,那么也许应该在ShellView本身中放置导航到LoginPromptViewModel的按钮。

Now back to your problem, since your MainViewModel extends Screen then it has a Parent property which refers to the Conductor, so you can do it like this: 现在回到您的问题,因为您的MainViewModel扩展了Screen那么它具有一个Parent属性,该属性引用了Conductor,因此您可以这样操作:

public void ShowLoginPrompt()
{
    LoginPromptViewModel lg = new LoginPromptViewModel();//This does happen
    var parentConductor = (Conductor)(lg.Parent);
    parentConductor.Activate(lg);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM