WPF Caliburn Micro:使用ContentControl动态交换窗口中的UserControl

Mag*_*agB 1 wpf user-controls contentcontrol caliburn.micro

此问题与动态添加用户控件到caliburm micro有关.在打开这个新线程之前,我已经阅读过任何其他相关的线程,但我仍然不明白并找不到解决方案.如果你们中的一些人认为这是重复的,请接受我的道歉.

我有一个窗口(MainView)包含2列的"主"网格(又名LayoutRoot).

左栏有2个按钮:"显示视图1"和"显示视图2".

  • 如果用户单击"显示视图1",则应在右列显示"Display1View"(UserControl包含带文本"View 1"的TextBlock),替换当前列.
  • 如果用户单击"显示视图2",则应在右列显示"Display2View"(UserControl包含带有文本"View 2"的TextBlock),替换当前列.

我的示例代码包含以下视图和视图模型:

  • MainView.xaml和MainViewModel.cs
  • Display1View.xaml和Display1ViewModel.cs
  • Display2View.xaml和Display2ViewModel.cs

在我的示例代码中,ContentControl无法识别UserControl.我究竟做错了什么?如何正确绑定ContentControl?请随意修改我的示例代码.先感谢您

MainView.xaml

<Window x:Class="TestCaliMiContentControl.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Main View"
    Width="525"
    Height="350">
    <Grid x:Name="LayoutRoot" ShowGridLines="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="30*" />
            <ColumnDefinition Width="100*" />
        </Grid.ColumnDefinitions>
        <StackPanel x:Name="LeftNavPanel" Grid.Column="0">
            <Button x:Name="Display1" Content="Display View 1" />
            <Button x:Name="Display2" Content="Display View 2" />
        </StackPanel>
        <ContentControl x:Name="MainGridContent" Grid.Column="1" />
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

MainViewModel.cs

public class MainViewModel : PropertyChangedBase
{
    private ContentControl _mainGridContent;
    public ContentControl MainGridContent
    {
        get { return _mainGridContent; }
        set
        {
            _mainGridContent = value;
            NotifyOfPropertyChange(() => MainGridContent);
        }
    }

    public void Display1()
    {
        //MainGridContent = new Display1ViewModel(); // cannot convert source type error
    }

    public void Display2()
    {
        // MainGridContent = new Display2ViewModel(); // cannot convert source type error          
    }
}
Run Code Online (Sandbox Code Playgroud)

Display1View.xaml

<UserControl x:Class="TestCaliMiContentControl.Display1View"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         d:DesignHeight="300"
         d:DesignWidth="300"
         mc:Ignorable="d">
    <Grid>
        <TextBlock HorizontalAlignment="Center" FontSize="72" 
                   Text="View 1"/>
     </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

Display1ViewModel.cs

using System;
using System.Windows.Controls;
using Caliburn.Micro;

namespace TestCaliMiContentControl
{
    public class Display1ViewModel : PropertyChangedBase {}
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*obi 6

首先,我首先建议您阅读Caliburn.Micro文档,特别是关于Screens,Conductors和Composition的部分:http://caliburnmicro.com/documentation/composition

话虽如此,我们可以修改您的代码以使其正常工作.

1)因为你MainViewModel应该进行其他物品,所以它应该来自Conductor<T>.在这种情况下,我们将进行Caliburn Screen课程.

public class MainViewModel : Conductor<Screen>
Run Code Online (Sandbox Code Playgroud)

2)在MVVM中,您查看模型应该对您的视图一无所知.你不应该看到UI类,如ContentControl.我们可以将您的属性更改为类型Screen,但实际上我们根本不需要该属性,因为我们使用的是指挥.因此,删除MainGridContent属性和支持字段.

3)在你Display1Display2方法中,调用Caliburn的指挥方法ActivateItem来显示适当的项目.

public void Display1()
{
    ActivateItem(new Display1ViewModel());
}
Run Code Online (Sandbox Code Playgroud)

4)在你的工作中MainView.xaml你需要将你绑定ContentControl到指挥的活动项目属性,这是按照惯例ActiveItem.

<ContentControl x:Name="ActiveItem" Grid.Column="1" />
Run Code Online (Sandbox Code Playgroud)

5)最后,由于你的指挥在进行Screen,你需要制作屏幕.屏幕很有用,因为它们具有生命周期并允许您知道它们何时被激活/停用.对Display1和Display2执行此操作.

public class Display1ViewModel : Screen {}
Run Code Online (Sandbox Code Playgroud)

这应该让你开始运行.