区域导航的简单实现
在学习Prism的时候不知道Prism的区域导航是如何实现的,然后看了一些讲解,下面是自己的一些总结。
这次的总结中主要包含如下的知识点:
1、DataTemplate 以及 DataType
2、ContentControl
什么是DataType?
DataTemplate中的DataType的功能实际上和Style中的TargetType很类似。
在Style中,使用了TargetType之后,如果不定义Style的Key,那么这个Style将会影响到它所在区域的所有TargetType控件的样式。
同理,在DataTemplate中,使用了DataType之后,如果不定义DataTemplate的Key,那么这个DataTemplate将应用于它所在区域,所有的以这个DataType为数据源的控件。
首先我们创建一个WPF项目:
这是项目结构,其中每个ViewModel都继承了Prism的 BindableBase ,这里用 Prism 主要是为了简单的使用它的MVVM框架。
US1ViewModel 页面中,我简单的讲其页面的颜色设置为红色:
<UserControl x:Class="BlankApp5.Views.US1View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BlankApp5.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="Red">
</Grid>
</UserControl>
US2ViewModel页面中,我简单的将其页面的颜色设置为黄色:
<UserControl
x:Class="BlankApp5.Views.US2View"
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:local="clr-namespace:BlankApp5.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid Background="Yellow" />
</UserControl>
在MainWindows中,我创建了两个DataTemple 并将其 DataType 设置为 两个Usercontrol 的Viewmodel :
xmlns:v="clr-namespace:BlankApp5.Views"
xmlns:vm="clr-namespace:BlankApp5.ViewModels"
<Window.Resources>
<DataTemplate DataType="{x:Type vm:US1ViewModel}">
<v:US1View />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:US2ViewModel}">
<v:US2View />
</DataTemplate>
</Window.Resources>
然后设置了一个简单的页面,如下图所示:
对应的代码:
<Window
x:Class="BlankApp5.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:Module1;assembly=Module1"
xmlns:m11="clr-namespace:Module1.Views;assembly=Module1"
xmlns:prism="http://prismlibrary.com/"
xmlns:v="clr-namespace:BlankApp5.Views"
xmlns:vm="clr-namespace:BlankApp5.ViewModels"
Title="{Binding Title}"
Width="1200"
Height="800"
prism:ViewModelLocator.AutoWireViewModel="True">
<Window.Resources>
<DataTemplate DataType="{x:Type vm:US1ViewModel}">
<v:US1View />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:US2ViewModel}">
<v:US2View />
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Grid.Column="0" Content="us1" Command="{Binding NagiveCommand}" CommandParameter="us1">
</Button>
<Button Grid.Column="2" Grid.Row="0" Content="us2" Command="{Binding NagiveCommand}" CommandParameter="us2"/>
<ContentControl Content="{Binding ContentViewModel}" Grid.Row="1" Grid.ColumnSpan="3"/>
</Grid>
</Window>
对应的MainWindowViewModel代码为:
using Module1.Common;
using Module1.Views;
using Prism.Commands;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
using System;
namespace BlankApp5.ViewModels
{
public class MainWindowViewModel : BindableBase
{
public MainWindowViewModel()
{
NagiveCommand = new DelegateCommand<string>(Nagive);
}
private void Nagive(string obj)
{
switch (obj)
{
case "us1":
ContentViewModel = US1ViewModel;
break;
case "us2":
ContentViewModel = US2ViewModel;
break;
default:
break;
}
}
public DelegateCommand<string> NagiveCommand { get; set; }
US1ViewModel US1ViewModel = new US1ViewModel();
US2ViewModel US2ViewModel = new US2ViewModel();
private BindableBase _ContentViewModel;
public BindableBase ContentViewModel
{
get { return _ContentViewModel; }
set { SetProperty(ref _ContentViewModel, value); }
}
上面的代码的意思为,当点击按钮的时候,触发NagiveCommand命令从而触发Nagive 方法,然后根据按钮所带的参数对 ContentViewModel 的值
进行设置,选择的参数不同,绑定的ViewModel也不同,在前端代码中,因为DataTemple 没有设置 自己的Key 那么这个数据模板将对所有的DataType 为这个类型所有的Control 应用这个DataTemple ,所以这里的CententControl 将会根据Centent 属性所Binding 不同的ViewModel 而选择不同的DataTemple ,再显示不同的View。