WPF Prims框架详解

文章目录

  • 前言
  • Prism基本使用
    • Prism选择,DryIoc还是Unity
    • Prism基本框架搭建
    • Prism动态更新
      • View和ViewModel对应关系
      • 参数动态更新
      • 函数动态绑定
    • prism新建项目模板
    • region
      • 使用事例
      • 测试是否限制空间
    • 消息订阅
      • 如何使用消息订阅
      • 使用建议
    • 路由导航
    • 对话框/弹窗功能
      • 实现代码

前言

Prims框架是WPF的一个框架,特点是集成了我们平常常用的开发模式,封装了很多常用的功能。例如消息通知,路由导航,Model绑定。

Prism基本使用

资料来源

WPF-Prism8.0核心教程(公益)

Prism选择,DryIoc还是Unity

根据网上的说明,DryIoc是更加效率更高的,但是我看Nuget下载数量里面,Unity下载数量比DryIoc高得多。具体没怎么用过,那就按照推荐用DryIoc好了。

Unity和DryIoc之间性能比较在这里插入图片描述

Prism基本框架搭建

在这里插入图片描述
在App.xaml里面,修改

App.xaml.cs

    /// <summary>/// 继承prism的PrismApplication类/// </summary>public partial class App : PrismApplication{//设置启动页protected override Window CreateShell(){//启动页为MainWindowreturn Container.Resolve<MainWindow>();}protected override void RegisterTypes(IContainerRegistry containerRegistry){}}

App.xaml

<!--xmlns:prism,引入prism命名空间-->
<!--prism:PrismApplication,继承prism下的PrismApplication类-->
<!--去掉StartupUrl,保证只有一个启动页-->
<prism:PrismApplication x:Class="PrismTest.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:PrismTest"xmlns:prism="http://prismlibrary.com/">
</prism:PrismApplication>

Prism动态更新

View和ViewModel对应关系

在这里插入图片描述
View和ViewModel可以自动绑定,命名要求为。

  • Model:NameViewModel
  • View:Name/NameView(两者都可以)
    在View中添加入如下代码
xmlns:prism引入命名空间
prism:ViewModel设置自动绑定
可以不加,默认进行了绑定。
<Window ...xmlns:prism="http://prismlibrary.com/"prism:ViewModelLocator.AutoWireViewModel="True">

也可以在App.xaml里面强行绑定

在原文件件中取消绑定

app.xaml

        /// <summary>/// 路由管理/// </summary>/// <param name="containerRegistry"></param>protected override void RegisterTypes(IContainerRegistry containerRegistry){//通过RegisterForNavigation进行强行绑定,强行让ViewA和ViewAViewModel进行绑定containerRegistry.RegisterForNavigation<ViewA, ViewAViewModel>();}

参数动态更新

	//继承BindableBase接口public class MyListBoxItem : BindableBase{private string text;public string Text{get { return text; }set {  SetProperty(ref text, value);}//此方法为Prism提供}}

可以输入propp加tab键,模板输入,提交写代码效率

在这里插入图片描述

函数动态绑定

函数动态绑定需要用到委托类型,如果委托不明白需要自己回去了解一下

viewModel


//声明委托
public DelegateCommand TestBtn { get; set; }
//构造函数
public MainWindowViewModel()
{//实例化委托TestBtn = new DelegateCommand(() =>{//执行内容});
}

view

使用Command引用委托,如果没有TestBtn委托也不报错<Button Content="测试方法"FontSize="100"Grid.Row="1"Command="{Binding TestBtn}"/>

prism新建项目模板

在扩展,管理扩展中安装
在这里插入图片描述
我们在新建程序的时候会有Prism模板框架

在这里插入图片描述

使用时会提示使用什么容器,这里推荐DryIoc容器

在这里插入图片描述

新建文件路径如下

在这里插入图片描述

region

Prism将界面继续划分,分为多个Region,在Region中添加元素。

在这里插入图片描述

和WPF用户组件的区别。

  • Region相当于划分了空区域,WPF是有内容的区域。
  • Region相当于WPF用户控件的上级,用于包含用户控件

使用事例

MainWindow.xaml

    <Grid><!--声明Region,名称为ContentRegion,使用名称来进行注入--><ContentControl prism:RegionManager.RegionName="ContentRegion" /></Grid>

UserControl1.xaml,用于放置在Region上面的用户控件

    <Grid><TextBlock  Text="我是用户控件" FontSize="100"/></Grid>

MainWindowViewModel.xaml

        //注册regionManager控件private readonly IRegionManager _regionManager;public MainWindowViewModel(IRegionManager regionManager){this._regionManager = regionManager;//ContentRegion是窗口已声明的Region,使用字符串进行弱绑定regionManager.RegisterViewWithRegion("ContentRegion",typeof(UserControl1));}

生成效果
在这里插入图片描述

测试是否限制空间

在这里插入图片描述

<Grid><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><!--声明Region,名称为ContentRegion,使用名称来进行注入--><ContentControl prism:RegionManager.RegionName="ContentRegion" /></Grid>

实现效果

在这里插入图片描述

消息订阅

消息订阅是先订阅再发布有效,如果是先发布再订阅则无效。

如何使用消息订阅

 public class MainWindowViewModel : BindableBase{private string _title = "Prism Application";//声明委托public DelegateCommand TestBtn { get; set; }public DelegateCommand SendCommand { get; set; }private readonly IEventAggregator _eventAggregator;public string Title{get { return _title; }set { SetProperty(ref _title, value); }}//构造函数public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator){//实例化委托//订阅TestBtn = new DelegateCommand(() =>{eventAggregator.GetEvent<MessageEvent>().Subscribe(OnMessageRecevied);});//发送SendCommand = new DelegateCommand(() =>{//执行参数eventAggregator.GetEvent<MessageEvent>().Publish("Hello Event");});this._eventAggregator = eventAggregator;}public void OnMessageRecevied(string msg){Title += msg + "\r\n";}//消息订阅类public class MessageEvent: PubSubEvent<string> {}}

注意
eventAggregator.GetEvent<MessageEvent>()。MessageEvent是我们自己定义的,相当于订阅的消息主题。

eventAggregator.GetEvent().

  • Subscribe(OnMessageRecevied);
    • OnMessageRecevied是处理函数
  • Publish(“Hello Event”)
    • "Hello Event"是入参,因为OnMessageRecevied(string msg)

取消订阅

eventAggregator.GetEvent<MessageEvent>().Unsubscribe(OnMessageRecevied);

使用建议

  • 注意,这个是全局使用的,所以一般用于页面通讯
    • 例如:AView。我就用AViewEvent。一个页面对应一个事件通知。
  • 由于带入的参数不一定,所以我们可以设置Dictionary为入参,通过key值过滤来设置对应的函数。通过NetJson来快速传参。

路由导航

路由导航和Region是搭配使用的,专门用于页面转化

  • 新建切换用的用户控件ViewA,ViewB,ViewC。ViewA,B,C内容有区分,这里省略
    在这里插入图片描述
  • 在App.xaml.cs中注册页面
        /// <summary>/// 路由管理/// </summary>/// <param name="containerRegistry"></param>protected override void RegisterTypes(IContainerRegistry containerRegistry){//将ViewA,B,C添加到导航,这样才能进行路由管理containerRegistry.RegisterForNavigation<ViewA>("ViewA");containerRegistry.RegisterForNavigation<ViewB>();containerRegistry.RegisterForNavigation<ViewC>();}
  • 在MainView中添加委托事件
   <Grid><Grid.RowDefinitions><RowDefinition Height="50"/><RowDefinition /></Grid.RowDefinitions><StackPanel Orientation="Horizontal"><Button Content="ViewA"Command="{Binding OpenACommand}" /><Button Content="ViewB"Command="{Binding OpenBCommand}" /><Button Content="ViewC"Command="{Binding OpenC_Command}" /><Button Content="上一页"Command="{Binding GoBackCommand}" /><Button Content="下一页"Command="{Binding GoForwordCommand}"/></StackPanel><!--这个Region是我们等会切换窗口信息的--><ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" /></Grid>

在MainiView里面管理导航


namespace PrismNavigation.ViewModels
{public class MainWindowViewModel : BindableBase{private string _title = "Prism Application";public string Title{get { return _title; }set { SetProperty(ref _title, value); }}/// <summary>/// 导航日志/// </summary>private IRegionNavigationJournal _journal;//Region,用于页面切换private readonly IRegionManager _regionManager;public DelegateCommand OpenACommand { get; set; }public DelegateCommand OpenBCommand { get; set; }public DelegateCommand OpenC_Command { get; set; }public DelegateCommand GoBackCommand { get; set; }public DelegateCommand GoForwordCommand { get; set; }public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator){_regionManager = regionManager;OpenACommand = new DelegateCommand(OpenA);OpenBCommand = new DelegateCommand(OpenB);OpenC_Command = new DelegateCommand(OpenC);GoBackCommand = new DelegateCommand(GoBack);GoForwordCommand = new DelegateCommand(GoForword);}private void OpenA(){NavigationParameters para = new NavigationParameters{{ "Value", "Hello Prism" }};//进行路由传参,ContentRegion是xmal中的Region名称,ViewA是在App.xmal中注册的名称,arg是日志回调,para是路由传递的参数_regionManager.RequestNavigate("ContentRegion", "ViewA", arg =>{///获取导航日志_journal = arg.Context.NavigationService.Journal;}, para);}private void OpenB(){_regionManager.RequestNavigate("ContentRegion", "ViewB", arg =>{///获取导航日志_journal = arg.Context.NavigationService.Journal;});}private void OpenC(){_regionManager.RequestNavigate("ContentRegion", "ViewC", arg =>{///获取导航日志_journal = arg.Context.NavigationService.Journal;});}private void GoForword(){_journal.GoForward();}private void GoBack(){_journal.GoBack();}}
}

在ViewA中进行路由拦截

 public class ViewAViewModel :BindableBase, IConfirmNavigationRequest{private string _name;public string Name{get { return _name; }set { SetProperty(ref _name, value); }}/// <summary>/// IConfirmNavigationRequest的路由离开拦截,/// </summary>/// <param name="navigationContext"></param>/// <param name="continuationCallback"></param>/// <exception cref="NotImplementedException"></exception>public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback){var res = true;if(MessageBox.Show("确认导航?","温馨提示",MessageBoxButton.YesNo) == MessageBoxResult.No){res = false;}//如果res为true则拦截,true则放行continuationCallback?.Invoke(res);}/// <summary>/// 用于判断是否要重新创建新的事例,即是否保留之前的信息,True为重新创建。/// </summary>/// <param name="navigationContext"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public bool IsNavigationTarget(NavigationContext navigationContext){return true;}/// <summary>/// 离开页面时触发,一般用于取消事件监听/// </summary>/// <param name="navigationContext"></param>/// <exception cref="NotImplementedException"></exception>public void OnNavigatedFrom(NavigationContext navigationContext){}/// <summary>/// 显示页面前触发,一般用于设置事件监听/// </summary>/// <param name="navigationContext"></param>/// <exception cref="NotImplementedException"></exception>public void OnNavigatedTo(NavigationContext navigationContext){//拿到Key为Value的值,返回类型为stringName = navigationContext.Parameters.GetValue<string>("Value");}}

实现效果
在这里插入图片描述

简单介绍

  • 路由导航是Region导航,必须要先将WPF用户控件添加到Region中才能进行导航
  • 在注册时,可以添加别名
    • containerRegistry.RegisterForNavigation<ViewA>(“别名”);
_regionManager.RequestNavigate("ContentRegion", "别名");//原本是ViewA的,可以替换成别名

对话框/弹窗功能

Prism将对话框这个常用的功能进行了封装。虽然叫对话框,但其实是弹窗的功能效果。

实现代码

app.xaml中

        /// <summary>/// 路由管理/// </summary>/// <param name="containerRegistry"></param>protected override void RegisterTypes(IContainerRegistry containerRegistry){.......//这里也能起别名containerRegistry.RegisterDialog<MsgView,MsgViewModel>("别名");   }

MainViewModel使用这个弹窗

public class MainWindowViewModel : BindableBase{private string _title = "Prism Application";public string Title{get { return _title; }set { SetProperty(ref _title, value); }}/// <summary>/// 导航日志/// </summary>private IRegionNavigationJournal _journal;private readonly IRegionManager _regionManager;//注册弹窗服务private IDialogService _dialogService;public DelegateCommand OpenACommand { get; set; }//构造函数中传入对话框public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator,IDialogService dialogService){_regionManager = regionManager;OpenACommand = new DelegateCommand(OpenA);GoForwordCommand = new DelegateCommand(GoForword);//使用对话框_dialogService = dialogService;}private void OpenA(){//对话框传递的参数DialogParameters param = new DialogParameters();param.Add("Value", "paramTest");//打开名为MsgView的弹窗,并传递参数_dialogService.Show("MsgView", param, arg =>{//弹窗关闭的回调函数,会有参数返回if(arg.Result == ButtonResult.OK){Debug.WriteLine("调试成功");}});}}

MsgView

<Grid Background="White"><Grid.RowDefinitions><RowDefinition Height="30" /><RowDefinition /><RowDefinition Height="50"/></Grid.RowDefinitions><TextBox Grid.Row="1" Text="{Binding Title}" FontSize="20"/><Label Content="{Binding Title}"/><DockPanel Grid.Row="2" LastChildFill="False"><Button Content="取消" Width="60"DockPanel.Dock="Right"Command="{Binding CancelCommand}" /><Button Content="确定"Width="60"DockPanel.Dock="Right"Command="{Binding SaveCommand}"/></DockPanel></Grid>
public class MsgViewModel :BindableBase, IDialogAware{private string _title;public string Title{get { return _title; }set { SetProperty(ref _title, value); }}/// <summary>/// 用于弹窗关闭的回调函数/// </summary>public event Action<IDialogResult> RequestClose;public DelegateCommand SaveCommand { get; set; }public DelegateCommand CancelCommand { get; set; }public MsgViewModel() {SaveCommand = new DelegateCommand(() =>{DialogParameters keyValuePairs = new DialogParameters();keyValuePairs.Add("Value", Title);//执行弹窗关闭,并传入回调参数RequestClose?.Invoke(new DialogResult(ButtonResult.OK, keyValuePairs));});CancelCommand = new DelegateCommand(() =>{RequestClose?.Invoke(new DialogResult(ButtonResult.No));});}/// <summary>/// 能否打开窗口/// </summary>/// <returns></returns>public bool CanCloseDialog(){return true;}/// <summary>/// 关闭的方法/// </summary>/// <exception cref="NotImplementedException"></exception>public void OnDialogClosed(){//throw new NotImplementedException();}/// <summary>/// 打开之前,接受弹窗传参/// </summary>/// <param name="parameters"></param>/// <exception cref="NotImplementedException"></exception>public void OnDialogOpened(IDialogParameters parameters){Title = parameters.GetValue<string>("Value");}}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/26370.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#开发的OpenRA游戏之维修按钮

C#开发的OpenRA游戏之维修按钮 前面分析物品的变卖按钮,如果理解这个流程,再看其它按钮的流程,其实是一样的,所以前面的文章是关键,只有理解通透的基础之上,才能继续往下。 维修按钮的存在价值,就是当建筑物受到敌方破坏,还没有完全倒掉之前,可以使用金币来进行修理。…

Redis学习(四)Redis原理:底层数据结构、网络模型、内存回收策略

文章目录 Redis底层数据结构SDS 动态字符串IntSet 整数集合Dict 字典Dict伸缩中的渐进式再哈希 ZipList 压缩列表QuickLisk 快速列表SkipList 跳表动态索引建立 RedisObject变量类型与数据结构实现StringListSetZSetHash Redis网络模型Redis是单线程还是多线程&#xff1f;为什…

用vscode远程连接Linux服务器后,如何创建自己的账号

1. 打开终端&#xff08;Terminal&#xff09;窗口 2. 在终端中创建新的用户账号 &#xff08;假设您要创建的用户名为 “newuser”&#xff09;&#xff0c;在命令执行期间&#xff0c;需要提供新用户的密码。按照提示进行操作。 先输入登录的管理员账号密码。 再输入创建的…

CMS系统访问权限限制

创建一些全局的通用方法 const USER_KEY "USER_KEY" const TOKEN_KEY "JWT_TOKEN_KEY"class Auth {constructor() {this.token nullthis.user nullthis.token localStorage.getItem(TOKEN_KEY)const userJson localStorage.getItem(USER_KEY)if (use…

大华监控前端实时预览(踩坑)

难点在后端&#xff0c;前端主要是文档太少了&#xff0c;前端难点主要是接入摄像头&#xff0c;摄像头接入了&#xff0c;剩下什么对讲、调整方向、变焦之类的就简单了。 大华官网&#xff1a;https://open-icc.dahuatech.com/#/home 1.到官网下载插件或者demo&#xff0c;我是…

SpringBoot + WebSocket+STOMP指定推送消息

目录 一、前提条件1.2 环境要求1.3 依赖 二、相关工具类准备2.1 发送消息载体2.2 接收消息载体2.3 消息处理接口2.4 为 STOMP 消息传递配置 Spring 三、前端部分四、效果 一、前提条件 本文将简单的描述SpringBoot WebSocketSTOMP指定推送消息场景&#xff0c;不包含信息安全加…

实时监测与报警,探索CMS系统在半导体设备安全管理中的作用

在半导体制造行业&#xff0c;设备的安全管理对于保障生产运行和员工安全至关重要。中央设备状态监控系统CMS&#xff08;central monitoring system&#xff09;是一种关键的解决方案&#xff0c;为企业提供实时监测和报警功能&#xff0c;有效应对设备安全管理的挑战。本文将…

网页动态表单 ,网页动态参数

有的时候因为参数太多 无法 一一 创建 所有采用动态创建 自己遇到的一个实际情况今天写个例子 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>form demo</title><link rel"stylesheet" href&quo…

Vit 实战营 Class2:图像与Transformer基础

文章目录 数组图像&#xff1a;图像与像素图像分类&#xff1a;机器如何学习&#xff1f;NMT&#xff1a;Neuron Machine TranslationTransformerVision Transformer代码实战 数组图像&#xff1a;图像与像素 什么是数字图像&#xff1f;在计算机图像的图像格式。每一个点叫pix…

工欲善其事,必先利其器之—react-native-debugger调试react native应用

调试react应用通常利用chrome的inspector的功能和两个最常用的扩展 1、React Developer Tools &#xff08;主要用于debug组件结构) 2、Redux DevTools &#xff08;主要用于debug redux store的数据&#xff09; 对于react native应用&#xff0c;我们一般就使用react-nativ…

ClickHouse

资料来源&#xff1a;尚硅谷ClickHouse 官方文档&#xff1a;什么是ClickHouse&#xff1f; | ClickHouse Docs 一、ClickHouse入门 1.1 ClickHouse特点 ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的列式存储数据库&#xff08;DBMS&#xff09;&#xff0c;使用 C语言编…

力扣算法数学类—Excel表列名称

目录 Excel表列名称 题解&#xff1a; 代码&#xff1a; Excel表列名称 168. Excel表列名称 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数 columnNumber &#xff0c;返回它在 Excel 表中相对应的列名称。 例如&#xff1a; A -> 1 B -> 2 C -> 3 ... Z -…