1.Prism框架介绍

  • 1.Prism框架介绍已关闭评论
  • 84 次浏览
  • A+
所属分类:.NET技术
摘要

什么是Prism :1.WPF Prism是一个用于构建模块化、可扩展和可重用的WPF应用程序的框架。它基于MVVM模式,提供了一种简单且灵活的方式来管理复杂的WPF应用程序。

什么是Prism

1.WPF Prism是一个用于构建模块化、可扩展和可重用的WPF应用程序的框架。它基于MVVM模式,提供了一种简单且灵活的方式来管理复杂的WPF应用程序。

2.Prism框架提供了一些核心概念,包括模块化开发、依赖注入、命令模式、导航和事件聚合等。它还提供了一些实用工具和类来简化开发过程,例如模块加载器、事件聚合器、导航器等。

3.Prism框架的主要目标是帮助开发人员构建易于维护和扩展的WPF应用程序,同时提高代码的可重用性和可测试性。

Github:https://github.com/PrismLibrary/Prism

Prism包括哪些功能模块

      1.Region(区域管理)
      2.Module(模块)
      3.View Injection(视图注入)
      4.ViewModelLocationProvider(视图模型定位)
      5.Command(绑定相关)
      6.Event Aggregator (事件聚合器)
      7.Navigation(导航)
      8.Dialog(对话框)

功能↓ / →框架名 Prism Mvvmlight Micorosoft.Toolkit.Mvvm
通知 BindableBase ViewModelBase ObservableObject
命令 DelegateCommand RelayCommand Async/RelayCommand
聚合器 IEventAggregator IMessenger IMessenger
模块化 × ×
容器 × ×
依赖注入 × ×
导航 × ×
对话 × ×

 

创建Prism应用程序:

第一步:创建WPF应用程序(我这里用NET6.0)

第二步:引用Prism.Unity框架

第三部:修改App.xaml文件

<prism:PrismApplication x:Class="WpfApp_test.App"              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"              xmlns:local="clr-namespace:Shell"              xmlns:prism="http://prismlibrary.com/">     <Application.Resources>         <ResourceDictionary>             <ResourceDictionary.MergedDictionaries>                             </ResourceDictionary.MergedDictionaries>         </ResourceDictionary>     </Application.Resources> </prism:PrismApplication>

 public partial class App : PrismApplication     {         protected override void RegisterTypes(IContainerRegistry containerRegistry)         {                       }          protected override Window CreateShell()         {             return Container.Resolve<MainWindow>();         } }

View和ViewModel实现绑定

添加Views和ViewModels文件夹,在Views文件夹里添加MainWindow.xaml和在ViewModels添加MainWindowViewModel.cs 

<Window x:Class="WpfApp_test.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:WpfApp_test.Views"         xmlns:prism="http://prismlibrary.com/"         prism:ViewModelLocator.AutoWireViewModel="True"             mc:Ignorable="d"         Title="MainWindow" Height="450" Width="800">     <Grid>     </Grid> </Window>

或者在App.cs中进行注册

 protected override void RegisterTypes(IContainerRegistry containerRegistry)         {             containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>();         }

亦或者在MainWindow.xaml.cs

this.DataContext = new MainWindowViewModel();

 

View和ViewModel数据绑定

<Window x:Class="WpfApp1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:WpfApp1.Views"         xmlns:prism="http://prismlibrary.com/"         xmlns:i="http://schemas.microsoft.com/xaml/behaviors"         mc:Ignorable="d"         Title="MainWindow" Height="450" Width="800">     <Grid>         <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">             <TextBlock Text="{Binding Title}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20"/>             <Button Content="确定" Command="{Binding TitleCommand}" Height="30" Width="50"/>             <Button  FontSize="30"  Content="带参数" Margin="10" Height="60" Command="{Binding GetParameterCommand}"  CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}}"/>             <Button x:Name="button" FontSize="30"  Content="behaviors带参数" Margin="10" Height="60" >                 <i:Interaction.Triggers>                     <i:EventTrigger EventName="Click">                         <i:InvokeCommandAction Command="{Binding BehaviorsClickCommand}" CommandParameter="{Binding ElementName=button}"/>                     </i:EventTrigger>                 </i:Interaction.Triggers>             </Button>         </StackPanel>             </Grid> </Window>

 public class MainWindowViewModel: BindableBase     {         private string _title;         public string Title         {             get { return _title; }             set { _title = value; RaisePropertyChanged(); }         }          public DelegateCommand TitleCommand { get; private set; }         public DelegateCommand<Button> GetParameterCommand { get; private set; }         public DelegateCommand<Button> BehaviorsClickCommand { get; private set; }          public MainWindowViewModel()         {             TitleCommand = new DelegateCommand(TitleAction);             GetParameterCommand = new DelegateCommand<Button>(GetParameterAction);             BehaviorsClickCommand = new DelegateCommand<Button>(BehaviorsClickAction);         }          private void TitleAction()         {             Title = "Prism应用程序!";         }         private void GetParameterAction(Button obj)         {             obj.Content = "GetParameter";         }         private void BehaviorsClickAction(Button obj)         {             obj.Content = "BehaviorsClick";         }     }

 

区域(Region)

页面显示的区域划分称N个Region, 此时, 每个Region将变成了动态分配区域。它将负责承担我们的UI组件或者控件。

1.Prism框架介绍

 

区域定义

添加一个用户控件页面Content.xaml

在MainWindow页面添加

 <ContentControl x:Name="Content" />

 <Grid Grid.Row="1">             <!--<ContentControl  prism:RegionManager.RegionName="{x:Static share:RegionNames.MainRegion}"/>-->             <ContentControl x:Name="Content" />         </Grid>

 

在MainWindow.xaml.cs

public partial class MainWindow : Window     {         public MainWindow(IRegionManager regionManager)         {             InitializeComponent();             //为界面元素注册区域             RegionManager.SetRegionName(Content, "ContentRegion");             //为指定区域指定页面             regionManager.RegisterViewWithRegion("ContentRegion", typeof(Content));          } }

在Prism中, 控件都支持注册Region, 只是有些控件需要自己实现一个RegionAdapters(区域适配器),Prism提供了许多内置得RegionAdapter。
如:ContentControlRegionAdapter ,ItemsControlRegionAdapter ,SelectorRegionAdapter等。

 

 模块(Module)

对于微服务的思想来说,对于特定功能服务都可以独立存在,在WPF中那么意味着, 每个独立的功能我们都可以称之为模块。

模块添加操作流程:

1.添加一个新的项目,WPF用户控件项目。

2.添加引用,Prism.Unity框架。

3.添加一个类。并继承于IModule,实现OnInitialized和RegisterTypes方法

4.添加两个文件夹Views和ViewModels

5.项目-->属性-->生成-->事件--生成后事件

xcopy "$(ProjectDir)binDebugnet6.0-windows$(ProjectName).dll" "$(SolutionDir)WPFClientbinDebugnet6.0-windowsModules" /Y /S xcopy "$(ProjectDir)binReleasenet6.0-windows$(ProjectName).dll" "$(SolutionDir)WPFClientbinReleasenet6.0-windowsModules" /Y /S

这个是生成该项目后,dll之间复制到主项目的bin目录下去。

6.在主项目WPFClient的bin目录下添加一个文件夹Modules。

7.在主项目的APP类文件里重写CreateModuleCatalog方法

protected override IModuleCatalog CreateModuleCatalog()         {             return new DirectoryModuleCatalog()             {                 ModulePath = AppContext.BaseDirectory + $"\Modules" //获取WPFModule.dll的目录             };         }

还有一种是通过引用项目的方法来添加

        /// <summary>         /// 通过引用来获取其它模块的页面         /// </summary>         /// <param name="moduleCatalog"></param>         protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)         {             base.ConfigureModuleCatalog(moduleCatalog);             moduleCatalog.AddModule<WPF.Common.CommonProfile>();//模块的IModule类         }

 

8.生成解决方法。

 

IRegionManager

怎样把子模块的页面呈现到主项目的ContentControl 区域中呢?

案列:

public class ImageModuleProfile : IModule     {         private readonly IRegionManager _regionManager;          public ImageModuleProfile(IRegionManager regionManager)         {             _regionManager = regionManager;         }           public void OnInitialized(IContainerProvider containerProvider)         {
//ImageView是子项目的页面, ContentControlName.MainmoduleImagemoduleReginName是区域的名称 _regionManager.RegisterViewWithRegion
<ImageView>(ContentControlName.MainmoduleImagemoduleReginName); } public void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterForNavigation<ImageView, ImageViewModel>(); } }

或者

_regionManager.RegisterViewWithRegion(ContentControlName.MainmoduleImagemoduleReginName, typeof(ImageView));

 

聚合器IEventAggregator

//创建事件 public class SavedEvent : PubSubEvent<string> { }  //发布 IEventAggregator.GetEvent<SavedEvent>().Publish("some value");  //订阅 IEventAggregator.GetEvent<SavedEvent>().Subscribe(.Subscribe(message=>             {                 //do something             });

 

Navigation导航功能

案例:

IRegionManager regionManager = …;//构造函数中获取 regionManager.RequestNavigate("RegionName", "ViewName");//跳转页面

带参数的跳转

var param = new NavigationParameters(); param.Add("Parameter", param); _regionManger.RequestNavigate("RegionName", "ViewName", param);  //类似URL地址传递参数 _regionManger.RequestNavigate("RegionName", "ViewName?id=1&Name=xiaoming");

INavigationAware

VM类继承该接口要实现3个方法

 public void OnNavigatedTo(NavigationContext navigationContext)         {          }          public bool IsNavigationTarget(NavigationContext navigationContext)         {             return true;         }          public void OnNavigatedFrom(NavigationContext navigationContext)         {          }

OnNavigatedTo: 导航完成前, 此处可以传递过来的参数以及是否允许导航等动作的控制。
IsNavigationTarget: 调用以确定此实例是否可以处理导航请求。否则新建实例
OnNavigatedFrom: 当导航离开当前页时, 类似打开A, 再打开B时, 该方法被触发。

接受跳转过来带的参数

public void OnNavigatedTo(NavigationContext navigationContext)         {             var id = navigationContext.Parameters.GetValue<int>("id");              var name = navigationContext.Parameters["Name"].ToString();         }

 

INavigationAware

该接口继承于INavigationAware, 所以, 它多了一个功能: 允许用户针对导航请求进行拦截。

//多了一个回调函数, 该值觉得是否拦截该导航请求     void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback);

当打开新的导航时, 或许有些情况下你需要经过用户进行确认, 这个时候, IConfirmNavigationRequest接口可以满足需求, 如下:

public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)         {             bool result = true;              if (MessageBox.Show("确认导航?", "温馨提示", MessageBoxButton.YesNo) == MessageBoxResult.No)                 result = false;              //通过回调当前返回的确认结果,决定是否启动该导航             continuationCallback(result);         }

Navigation Journal
导航日志, 其实就是对导航系统的一个管理功能, 理论上来说, 我们应该知道我们上一步导航的位置、以及下一步导航的位置, 包括我们导航的历史记录。以便于我们使用导航对应用程序可以灵活的控制。

IRegionNavigationJournal
该接口包含以下功能:

GoBack() : 返回上一页
CanGoBack : 是否可以返回上一页
GoForward(): 返回后一页
CanGoForward : 是否可以返回后一页

 

IDialogAware对话框

public interface IDialogAware { string Title { get; } event Action<IDialogResult> RequestClose; bool CanCloseDialog(); void OnDialogClosed(); void OnDialogOpened(IDialogParameters parameters); }

注册对话框 RegisterDialog

protected override void RegisterTypes(IContainerRegistry containerRegistry)         {             //仅注册视图             containerRegistry.RegisterDialog<MessageDialog>();              //注册视图时绑定VM             containerRegistry.RegisterDialog<MessageDialog, MessageDialogViewModel>();              //添加别名             containerRegistry.RegisterDialog<MessageDialog>("DialogName");         }

使用IDialogService接口 Show/ShowDialog 方法调用对话框

private readonly IDialogService dialogService;          private void ShowDialog()         {             DialogParameters keys = new DialogParameters();             keys.Add("message", "Hello,Prism!");              dialogService.ShowDialog("MessageDialog", keys, arg =>             {                              });         }