WPF Caliburn Micro:使用 ContentControl 在 Window 中动态交换 UserControl
WPF Caliburn Micro: Exchanging UserControls in a Window dynamically using ContentControl
此问题与 Add a usercontrol to caliburm micro dynamically 有关。
在打开这个新线程之前,我已经阅读了任何其他相关线程,但我仍然不明白并且找不到解决方案。如果有人认为这是重复的,请接受我的道歉。
我有一个 window (MainView) 包含 "main" 网格(又名 LayoutRoot)和 2 列。
左栏有 2 个按钮:"Display View 1" 和 "Display View 2"。
- 如果用户单击 "Display View 1","Display1View"(是一个包含 TextBlock 和文本 "View 1" 的 UserControl)应该显示在右栏中,替换当前的。
- 如果用户单击 "Display View 2","Display2View"(是一个包含 TextBlock 和 Text "View 2" 的 UserControl)应该显示在右栏中,替换当前的。
我的示例代码包含以下视图和视图模型:
- 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>
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
}
}
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>
Display1ViewModel.cs
using System;
using System.Windows.Controls;
using Caliburn.Micro;
namespace TestCaliMiContentControl
{
public class Display1ViewModel : PropertyChangedBase {}
}
首先,我建议您阅读 Caliburn.Micro 文档,特别是关于屏幕、导体和组合的部分:http://caliburnmicro.com/documentation/composition
也就是说,我们可以修改您的代码以使其正常工作。
1) 由于您的 MainViewModel
应该进行其他项目,因此它应该来自 Conductor<T>
。在这种情况下,我们将让它进行 Caliburn Screen
class.
public class MainViewModel : Conductor<Screen>
2) 在 MVVM 中,你的视图模型应该对你的视图一无所知。您不应看到 UI class 等 ContentControl
。我们可以将您的 属性 更改为 Screen
类型,但实际上我们根本不需要 属性,因为我们使用的是导体。因此,删除 MainGridContent
属性 和支持字段。
3) 在您的 Display1
和 Display2
方法中,调用 Caliburn 的指挥方法 ActivateItem
以显示适当的项目。
public void Display1()
{
ActivateItem(new Display1ViewModel());
}
4) 在您的 MainView.xaml
中,您需要将 ContentControl
绑定到指挥的活动项目 属性,按照惯例,ActiveItem
.
<ContentControl x:Name="ActiveItem" Grid.Column="1" />
5) 最后,由于您的导体正在传导 Screen
s,您需要将它们制作成屏幕。屏幕很有用,因为它们具有生命周期并让您知道它们何时 activated/deactivated。对 Display1 和 Display2 执行此操作。
public class Display1ViewModel : Screen {}
这会让你起床 运行。
此问题与 Add a usercontrol to caliburm micro dynamically 有关。 在打开这个新线程之前,我已经阅读了任何其他相关线程,但我仍然不明白并且找不到解决方案。如果有人认为这是重复的,请接受我的道歉。
我有一个 window (MainView) 包含 "main" 网格(又名 LayoutRoot)和 2 列。
左栏有 2 个按钮:"Display View 1" 和 "Display View 2"。
- 如果用户单击 "Display View 1","Display1View"(是一个包含 TextBlock 和文本 "View 1" 的 UserControl)应该显示在右栏中,替换当前的。
- 如果用户单击 "Display View 2","Display2View"(是一个包含 TextBlock 和 Text "View 2" 的 UserControl)应该显示在右栏中,替换当前的。
我的示例代码包含以下视图和视图模型:
- 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>
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
}
}
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>
Display1ViewModel.cs
using System;
using System.Windows.Controls;
using Caliburn.Micro;
namespace TestCaliMiContentControl
{
public class Display1ViewModel : PropertyChangedBase {}
}
首先,我建议您阅读 Caliburn.Micro 文档,特别是关于屏幕、导体和组合的部分:http://caliburnmicro.com/documentation/composition
也就是说,我们可以修改您的代码以使其正常工作。
1) 由于您的 MainViewModel
应该进行其他项目,因此它应该来自 Conductor<T>
。在这种情况下,我们将让它进行 Caliburn Screen
class.
public class MainViewModel : Conductor<Screen>
2) 在 MVVM 中,你的视图模型应该对你的视图一无所知。您不应看到 UI class 等 ContentControl
。我们可以将您的 属性 更改为 Screen
类型,但实际上我们根本不需要 属性,因为我们使用的是导体。因此,删除 MainGridContent
属性 和支持字段。
3) 在您的 Display1
和 Display2
方法中,调用 Caliburn 的指挥方法 ActivateItem
以显示适当的项目。
public void Display1()
{
ActivateItem(new Display1ViewModel());
}
4) 在您的 MainView.xaml
中,您需要将 ContentControl
绑定到指挥的活动项目 属性,按照惯例,ActiveItem
.
<ContentControl x:Name="ActiveItem" Grid.Column="1" />
5) 最后,由于您的导体正在传导 Screen
s,您需要将它们制作成屏幕。屏幕很有用,因为它们具有生命周期并让您知道它们何时 activated/deactivated。对 Display1 和 Display2 执行此操作。
public class Display1ViewModel : Screen {}
这会让你起床 运行。