什么是区域(Region)?
在理解这个之前, 首先需要了解一下, 在最常见的开发模式当中, 我们去设计某个页面的时候, 实际上界面元素在设计的时候已经被固定。
因此我们可以为这个页面设计一些元素, 例如:
MainWindow代码
<Window
x:Class="PrismApp.Views.MainWindow"
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:PrismApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}"
Width="800"
Height="450"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="9*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button
MinWidth="80"
Margin="3"
Command="{Binding OpenCommand}"
CommandParameter="ViewA"
Content="打开模块A"
FontSize="12" />
<Button
MinWidth="80"
Margin="3"
Command="{Binding OpenCommand}"
CommandParameter="ViewB"
Content="打开模块B"
FontSize="12" />
<Button
MinWidth="80"
Margin="3"
Command="{Binding OpenCommand}"
CommandParameter="ViewC"
Content="打开模块C"
FontSize="12" />
</StackPanel>
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
1定义切换视图的按钮
2.定义区域
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
添加3个用户控件,用于显示到区域中
<UserControl x:Class="PrismApp.Views.ViewA"
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:PrismApp.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="AliceBlue">
<TextBlock Text="ViewA" FontSize="90" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</UserControl>
另外连个视图添加相同
依赖注入
App.Xaml.cs代码
public partial class App : PrismApplication
{
protected override Window CreateShell()//启动页
{
return Container.Resolve<Views.MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)//依赖注入
{
//注入视图
containerRegistry.RegisterForNavigation<ViewA>();
containerRegistry.RegisterForNavigation<ViewB>();
containerRegistry.RegisterForNavigation<ViewC>();
}
}
注入视图
//注入视图
containerRegistry.RegisterForNavigation<ViewA>();
containerRegistry.RegisterForNavigation<ViewB>();
containerRegistry.RegisterForNavigation<ViewC>();
注册区域
MainWindowViewModle代码
namespace PrismApp.ViewModels
{
internal class MainWindowViewModel:BindableBase
{
private string _title="Prism App"; //标题
public string Title
{
get { return _title; }
set { SetProperty(ref _title,value); }
}
public DelegateCommand<string> OpenCommand { get; private set; }
private readonly IRegionManager regionManager;
public MainWindowViewModel(IRegionManager regionManager) //注册区域
{
OpenCommand =new DelegateCommand<string>(Open);
this.regionManager = regionManager;
//#region 注册区域
//regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
//regionManager.RegisterViewWithRegion("ContentRegion2", typeof(ViewB));
//regionManager.RegisterViewWithRegion("ContentRegion3", typeof(ViewC));
//#endregion
}
private void Open(string obj)//页面切换方法
{
regionManager.Regions["ContentRegion"].RequestNavigate(obj);
}
}
}
注册区域
private readonly IRegionManager regionManager;
public MainWindowViewModel(IRegionManager regionManager) //注册区域
{
this.regionManager = regionManager;
}
视图切换命令
public DelegateCommand<string> OpenCommand { get; private set; }//定义命令
OpenCommand =new DelegateCommand<string>(Open);//初始化
private void Open(string obj)//页面切换方法
{
regionManager.Regions["ContentRegion"].RequestNavigate(obj);
}
*初始化显示注册的区域(可以设置多个区域显示)
//#region 初始化注册区域
regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
//regionManager.RegisterViewWithRegion("viewB", typeof(ViewB));
//regionManager.RegisterViewWithRegion("viewC", typeof(ViewC));
//#endregion
注意事项
细心的网友可能已经看到了, 上面的代码中, 为3个ContentControl注册了对应的区域, 然后显示3个自定义的控件。
那么, 是不是同样可以在其它控件元素上注册Region?
是的, 在Prism中, 控件都支持注册Region, 只是有些控件需要自己实现一个RegionAdapters(区域适配器)
什么是RegionAdapters?
假设在应用程序的某个区域, 需要显示我们定义的视图,这个时候实际上利用了RegionAdapter。
该类负责将传入我们定义的视图到指定的Region当中。
Prism提供了许多内置得RegionAdapter
ContentControlRegionAdapter
ItemsControlRegionAdapter
SelectorRegionAdapter
- ComboBox
- ListBox
- Ribbon
- TabControl
注:除此之外, 如果想要实现控件作用域Region, 则必须创建自己的自定义Region, 因为一旦你不这么做, 则会引发异常。
自定义StackPanel 区域适配器
StackPanelRegionAdapter类代码
namespace PrismApp
{
/// <summary>
/// 自定义StackPanel区域
/// </summary>
internal class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
{
/// <summary>
/// 构造方法
/// </summary>
/// <param name="regionBehaviorFactory"></param>
public StackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory)
{
}
/// <summary>
/// 动态添加内容,检测区域有控件添加
/// </summary>
/// <param name="region"></param>
/// <param name="regionTarget"></param>
protected override void Adapt(IRegion region, StackPanel regionTarget)
{
region.Views.CollectionChanged += (s, e) =>
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (FrameworkElement item in e.NewItems)
{
regionTarget.Children.Add(item);
}
}
};
}
/// <summary>
/// 创建Region区域
/// </summary>
/// <returns></returns>
protected override IRegion CreateRegion()
{
return new Region();
}
}
}
App.Xaml.cs中初始化自定义StackPanel区域适配器
/// <summary>
/// 初始化自定义StackPanel
/// </summary>
/// <param name="regionAdapterMappings"></param>
protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
{
base.ConfigureRegionAdapterMappings(regionAdapterMappings);
regionAdapterMappings.RegisterMapping(typeof(StackPanel),
Container.Resolve<StackPanelRegionAdapter>());
}