当前位置: 首页 > news >正文

【Prism系列】Region的用法

前言

    Prism中的Region可以和WPF中提供的Frame进行类比,Frame通过加载不同的Page达到界面导航的效果。Region也有相同的作用,不过Region有Psrim框架以及容器的加持,能够支持更细致化的导航控制,更轻松的传参, 更方便的生命周期管理,以及提供更加松的耦合,等等。Region的整个套路和上一篇文章《Prism子窗口实现》有着很多共同之处,大家可以对照学习。

注册与注入

和上篇一样,我们准备几个用户控件用来充当导航的内容。同样准备的内容,我们可以提前注册到容器中。上篇中我们使用:containerRegistry.RegisterDialog<MyDialog>(); 注册了子窗口,这次我们使用 containerRegistry.RegisterForNavigation<MyDialog>();  将MyDialog整个控件注册成导航需要的界面。不过这次为了导航效果再准备一个叫MyView的控件。

讲《Prism子窗口实现》的时候,Prism为我们准备了IDialogService管理窗口。同样的Prism也为我们提供了一个叫IRegionManager的对象管理Region。这里我们可以直接注入:

[Dependency]
public IRegionManager regionManager { get; set; }

前台区域划分

接下来,我们需要再前台画出一片区域,并且給这片区域起个名字:(xmlns:prism="http://prismlibrary.com/"

<ContentControl Grid.Row="1" Grid.Column="1" prism:RegionManager.RegionName="MainRegion"/>

这貌似就是给ContentControl添加了一个附加属性啊?为啥是ContentControl?这里涉及到Region适配器的相关内容,我这里暂且不表。现在只需理解为,ContentControl所在的这篇区域就是划分出来的Region,并且名字叫做MainRegion。

这里需要注意一个问题,Region区域需要定义到顶层Windows,如果定义到子界面比如Page中,会导致区域名称识别不到(即使通过RegisterViewWithRegion注册,切换界面也会有切换不了的问题)。

其实Region只需要存在于主界面,就能解决我们的所有需求,无非是多划分几个区域而已,并不需要嵌套。

关系建立

现在内容准备好了,区域也划分好了,现在需要讲内容和区域建立关系。

regionManager.RequestNavigate("MainRegion", "MyDialog");

MainRegion是区域的名字,MyDialog是要显示内容的类名称。

下面提供完整的测试代码:

<ContentControl Grid.Row="1" Grid.Column="1" prism:RegionManager.RegionName="MainRegion"/>
<StackPanel Grid.Row="1">
    <Button Content="界面1" Command="{Binding BtnCommand}" CommandParameter="MyDialog"/>
    <Button Content="界面2" Command="{Binding BtnCommand}" CommandParameter="MyView"/>
</StackPanel>
[Unity.Dependency]
public IRegionManager regionManager { get; set; }
public Region的用法ViewModel()
{
    BtnCommand = new DelegateCommand<string>(Do);
}
void Do(string str)
{
    regionManager.RequestNavigate("MainRegion", str);
}

测试效果:

 Region适配器

首先要说明的是,RequestNavigate的是单例模式,相同的类只会往区域里添加一次。为了证明这一点,我们换一个适配器看看,之前我们用的是,ContentControl。现在换成ItemsControl试试:

<ScrollViewer Grid.Column="2" >
    <ItemsControl  prism:RegionManager.RegionName="MainRegion"/>
</ScrollViewer>

其余的不变,效果如下:

最明显的区别是,当 ContentControl换成ItemsControl后,切换界面,变成了添加了两个界面。

这个就是适配器带来的区别。

其实要注意是,不过切换多少次,最多只能添加两个。这就是RequestNavigate的单例的特性。

如果像添加多个,需要将RequestNavigate换成AddToRegion:

regionManager.AddToRegion("MainRegion", str);

效果如下:

 从这里我们可以看到,RequestNavigate是用于单个界面的切换,通常和ContentControl配合使用。而AddToRegion是用于界面的添加,或者说是多个界面的嵌入,通常和ItemsControl配合使用。

其实将区域和内容建立关系的函数,除了RequestNavigate和AddToRegion,其实还有一个RegisterViewWithRegion。如果换成RegisterViewWithRegion,你会发现这个效果和AddToRegion是一模一样的。它和AddToRegion的区别在于,它额外包含注册部分,也就是之前再App中注册的部分可以省略掉:

containerRegistry.RegisterForNavigation<MyDialog>();
containerRegistry.RegisterForNavigation<MyView>();

适配器的种类

  • ContentControlRegionAdapter: ContentControl
  • ItemsControlRegionAdapter: ItemsControl
  • SelectorRegionAdapter
    - ComboBox
    - ListBox
    - Ribbon
    - TabControl

也就是说,并不是任何的控件,都能最为区域,符合上述适配器的要求控件才能作为Region。

大家可以尝试不用控件作为区域会是什么效果,比如TabControl。后续随着研究的深入,我再进行内容的补充吧。

prism还停供了接口,让我们可以自定义适配器(暂时不去研究了)。

Region的生命周期

        通过管理的界面,是有IOC加持的,所以有生命周期的概念,我们知道,每次当Page切换时,Page其实经历了Unload的和Load的过程,之前界面修改的内容,切换后都会被重置。

但是Region默认会被保存到IOC里(本质在内存中保存),所以切换界面,界面不会被重置。

但是,如果我们也可以让其切换后重置。只需要让控件界面对应的ViewModel实现接口IRegionMemberLifetime即可。这个接口里只有一个KeepAlive变量,将其置为false即可。

public bool KeepAlive => false;
//或者写成:
public bool KeepAlive { get; } = false;

导航确认

导航确认,就是跳转时可能会有几个步骤,prism框架提供几个回调,让我们的代码可以参与其中。让控件界面对应的ViewModel实现接口IConfirmNavigationRequest:

当我们调用RequestNavigate时,离开当前页面A会调用A的ConfirmNavigationRequest,确认是否离开,如确认离开,则继续调用A的OnNavigatedFrom,去到另外一个页面B,会调用B的IsNavigationTarget,表示返回一个新的界面还是IOC里已经有的,然后继续调用OnNavigatedTo表示已经来到B界面。

#region 导航确认
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
    // 确认是否离开当前视图
    bool result=true;

    //if (MessageBox.Show("Do you to navigate?", "Navigate?", MessageBoxButton.YesNo) == MessageBoxResult.No)
    //{ result = false; } 
    //else
    //{ result = true;  }

    continuationCallback(result);
}


public void OnNavigatedTo(NavigationContext navigationContext)
{
    //来到当前试图
    var value = navigationContext.Parameters["value"];
}

public bool IsNavigationTarget(NavigationContext navigationContext)
{
    // 当切换到本界面时:
    // 当返回True的时候,返回容器里面的view
    // 当返回 False的时候,返回一个新的view
    // 和 KeepAlive时相同的意思
    return ture;
}

public void OnNavigatedFrom(NavigationContext navigationContext)
{
    // 离开当前视图
}
#endregion

这里说明几个点:

ConfirmNavigationRequest:里面有个回调函数,调用时如果传true,表示可以跳转。如果为false表示不可以跳转。如果不调用这个回调,也无法跳转。

IsNavigationTarget:如果你是为了切换界面,这里IsNavigationTarget永远返回true,不要返回false。返回false会导致新的界面产生旧的还在,这样随着界面切换的次数增加,IsNavigationTarget被框架调用的次数随着增加,内存也变大。

如果你想返回一个新的界面,应该使用KeepAlive=>false ,这样不会导致该问题!

导航传参

在调用regionManager.RequestNavigate的时候,可以多传一个参数:

NavigationParameters para = new NavigationParameters();
para.Add("key", "any");
regionManager.RequestNavigate("MainRegion", "MyView", para);

那么在实现接口IConfirmNavigationRequest的函数里都有一个参数: navigationContext,

这个参数中就会包含RequestNavigate传进来的参数对象了:

最后,欢迎大家,点赞+关注。

相关文章:

  • 51单片机
  • 工匠精神育种陈温福培育一粒好种子 国稻种芯百团计划行动
  • MybatisPlus基本查询
  • 《MySQL实战45讲》——学习笔记01 “MySQL基本架构、redo log两阶段提交、事务隔离“
  • 【Selenium】一键摸鱼 一键采集数据
  • 配置编译设置
  • Spyder故障基本解决方案 (包括闪退)-超全版本
  • 第一篇 如何选择深度学习主机
  • MATLAB2016a生成COM组件及调用说明
  • 抖音、饿了么协同作战?
  • springboot设置并获取启动参数
  • PMP_考前冲刺题 二 (3A通过分享)(2022.7)(75题附答案及解析)
  • php毕业论文参考文献计算机毕业设计剧影评|剧评影评系统
  • 《深入理解JAVA虚拟机(第2版)》—— 学习笔记1
  • Idean中的Maven
  • JavaScript-如何实现克隆(clone)函数
  • Babel配置的不完全指南
  • Docker入门(二) - Dockerfile
  • github从入门到放弃(1)
  • input的行数自动增减
  • Java,console输出实时的转向GUI textbox
  • MySQL的数据类型
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • PAT A1120
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • spring security oauth2 password授权模式
  • text-decoration与color属性
  • 安装python包到指定虚拟环境
  • 从零开始在ubuntu上搭建node开发环境
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 记一次和乔布斯合作最难忘的经历
  • 数据结构java版之冒泡排序及优化
  • 学习Vue.js的五个小例子
  • 一些关于Rust在2019年的思考
  • No resource identifier found for attribute,RxJava之zip操作符
  • 阿里云ACE认证学习知识点梳理
  • "无招胜有招"nbsp;史上最全的互…
  • # Panda3d 碰撞检测系统介绍
  • ###STL(标准模板库)
  • #1014 : Trie树
  • #前后端分离# 头条发布系统
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (定时器/计数器)中断系统(详解与使用)
  • (二)c52学习之旅-简单了解单片机
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (转) 深度模型优化性能 调参
  • (转)c++ std::pair 与 std::make
  • (转)清华学霸演讲稿:永远不要说你已经尽力了
  • ***利用Ms05002溢出找“肉鸡
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .netcore 获取appsettings
  • .NET连接数据库方式
  • [C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改