C# 从另一个ViewModel设置Caliburn.Micro ControlContent

C# 从另一个ViewModel设置Caliburn.Micro ControlContent,c#,wpf,caliburn.micro,C#,Wpf,Caliburn.micro,我是Caliburn.Micro(以及MVVM)的新手,我正试图通过子viewmodel(由导体调用的)中的按钮激活位于ShellViewModel中的导体的屏幕。我看到的所有教程在实际的shell中都有按钮,可以在两者之间切换,所以我有点迷茫 所有视图模型共享名称空间SafetyTraining.ViewModels ShellViewModel(第一次使用shell,所以我可能使用错误的方式) MainViewModel-主屏幕(显示正确) MainViewXAML <UserCon

我是Caliburn.Micro(以及MVVM)的新手,我正试图通过子viewmodel(由导体调用的)中的按钮激活位于
ShellViewModel
中的导体的屏幕。我看到的所有教程在实际的shell中都有按钮,可以在两者之间切换,所以我有点迷茫

所有视图模型共享名称空间
SafetyTraining.ViewModels

ShellViewModel
(第一次使用shell,所以我可能使用错误的方式)

MainViewModel
-主屏幕(显示正确)

MainView
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>
<Button cal:Message.Attach="[Event Click] = [ShowLoginPrompt]">Login</Button> 
编辑工作代码:

稍微修改了嗅探器的代码,以适合我的结构。谢谢:)

var parentConductor=(Conductor.Collection.OneActive)(this.Parent);
parentConductor.ActivateItem(新登录ComptViewModel());

您做的每件事都是正确的,但您缺少一件事:

public void ShowLoginPrompt()
{
    LoginPromptViewModel lg = new LoginPromptViewModel();//This does happen
}
您正在创建一个
LoginPromptViewModel
的实例,但您没有告诉导体激活此实例,因此它的
OnActivate()
方法从未被调用

现在,在我给大家一个解决方案之前,我应该提出几点建议:

  • 如果使用
    MainViewModel
    在不同的视图模型之间导航,则将
    MainViewModel
    本身设置为导体是合适的

  • 如果您不是这样使用它,那么您可能应该在
    ShellView
    本身中放置导航到
    LoginComptViewModel
    的按钮

  • 现在回到您的问题,因为您的
    MainViewModel
    扩展了
    Screen
    ,所以它有一个
    Parent
    属性,它引用导体,所以您可以这样做:

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

    是自定义差异还是版本差异(我使用的是1.5.2),您通过Conductor no param(对我无效)和Active而不是ActivateItem来实现?只是wondering@PRX对不起,我不完全明白你在问什么?
    public class LoginPromptViewModel : Screen
    {
        protected override void OnActivate()
        {
            base.OnActivate();
            MessageBox.Show("Hi");//This is for testing - currently doesn't display
        }
    }
    
    var parentConductor = (Conductor<object>.Collection.OneActive)(this.Parent);
            parentConductor.ActivateItem(new LoginPromptViewModel());
    
    public void ShowLoginPrompt()
    {
        LoginPromptViewModel lg = new LoginPromptViewModel();//This does happen
    }
    
    public void ShowLoginPrompt()
    {
        LoginPromptViewModel lg = new LoginPromptViewModel();//This does happen
        var parentConductor = (Conductor)(lg.Parent);
        parentConductor.Activate(lg);
    }