首页 > 其他分享 >Prism框架

Prism框架

时间:2024-01-25 14:47:49浏览次数:20  
标签:regionManager 框架 void private Prism 导航 public 页面

1.搭建

(1)通过NuGet安装程序包Prism.DryIoc

(2)在App.xaml中引用Prism命名空间,项目应用对象改为PrismApplication,并且删除StartupUri

<prism:PrismApplication x:Class="WpfApp1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp1"
             xmlns:prism="http://prismlibrary.com/">
</prism:PrismApplication>

 (3)App.xaml.cs 实现接口由Application-->PrismApplication,并实现接口方法。

public partial class App : PrismApplication
{
    // 关系:PrismApplication 继承于 PrismApplicationBase 继承于 Application
    // CreateShell()主要负责启动一个主页面。
    protected override Window CreateShell()
    {
        return Container.Resolve<Main>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
    }
}

(4)动态绑定上下文

满足以下三条,不需要XXX.xaml.cs中手动绑定DataContext,实现自动绑定ViewModel。

  • 窗体|页面|用户控件必须放到Views文件夹下
  • 模型必须放到ViewModels文件夹下
  • 模型l的名称,必须是窗体名称开头,且以ViewModel结尾
  • 自动绑定设置 prism:ViewModelLocator.AutoWireViewModel="True"(可省略)

 

2.区域

(1)添加ContentControl 用来存放区域

<Window x:Class="WpfApp1.Views.Main"
        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"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <!--命令绑定,传入参数CommandParameter-->
            <Button Command="{Binding OpenCommand}" CommandParameter="PageA" Content="打开模块A" Margin="5"/>
        </StackPanel>
        <ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion"></ContentControl>
    </Grid>
</Window>

(2)新建用户控件

<UserControl x:Class="WpfApp1.Views.PageA"
             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:WpfApp1.Views"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBlock Text="我是PageA" FontSize="70"/>
    </Grid>
</UserControl>

在App.xaml.cs中注册用户控件

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.RegisterForNavigation<PageA>();
}

(3)在ViewModel中通过区域找到用户控件

namespace WpfApp1.ViewModels
{
    public class MainViewModel:BindableBase
    {
        private readonly IRegionManager regionManager;
        public DelegateCommand<string> OpenCommand { get; private set; }
        //把接口 IRegionManager 注入 
        public MainViewModel(IRegionManager regionManager)
        {
            OpenCommand = new DelegateCommand<string>(Open);
            this.regionManager = regionManager;
        }

        void Open(string name)
        {
            //通过regionManager接口获取当前全局定义的可用区域
            //通过依赖注入的方式动态的往这个区域注入内容
            this.regionManager.Regions["ContentRegion"].RequestNavigate(name);
        }
    }
}

 

4.模块化

模块化功能和区域相似,但模块化范围更广,它是将项目当作模块来充当跳转页面(因此项目中的view需要是用户控件)。而区域只是把用户控件当作跳转界面。

(1)新建模块类库项目

(2)添加用户控件PageA

(3)添加XXXProfile类,并实现IMoudle接口

注意:区域注册是在App.xaml.cs中,而模块是在此文件中注册

class ModuleProfile : IModule
{
    public void OnInitialized(IContainerProvider containerProvider)
    {
      
    }

    public void RegisterTypes(IContainerRegistry containerRegistry)
    {
        //<视图,视图模型>上下文绑定
        containerRegistry.RegisterForNavigation<PageA,PageAViewModel>();
    }
}

(4)在主程序App.xaml.cs中管理注册的模块

方式一:引用模块dll,重写ConfigureModuleCatalog方法
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
    //ConfigureModuleCatalog()主要负责把依赖的模块添加到Prism框架中进行管理.
    moduleCatalog.AddModule<ModuleProfile>();
    base.ConfigureModuleCatalog(moduleCatalog);
}
方式二:重写CreateModuleCatalog方法,不需要引用模块dll 从指定目录中查找所有符合约定的程序集。将依赖的模块dll复制到该目录下。
protected override IModuleCatalog CreateModuleCatalog()
{
      //查找目录中所有符合约定的程序集,添加到Prism框架中
    return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
}
也可以通过配置文件app.config实现模块化,将模块dll放置到主项目输出路径下。        
protected override IModuleCatalog CreateModuleCatalog()
{
    return new ConfigurationModuleCatalog();
}

配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
		<section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf"/>
	</configSections>
	<startup>
		<supportedRuntime version="v5.0" sku=".NETFramework,Version=v4.7.2" />
	</startup>
	<modules>
		<module assemblyFile="ModuleA.dll" 
				moduleType="ModuleA.ModuleProfile, ModuleA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 
				moduleName="ModuleProfile" startupLoaded="True" />
	</modules>
</configuration>

 

5.导航

导航实在区域的基础上实现的,除了可以区域页面跳转外还可以实现传参, 导航确认,导航拦截,导航日志等。

(导航执行顺序)

(1)传参

主窗体通过NavigationParameters设置参数,并通过RequestNavigate传递给导航窗体。
void Open(string name)
{
    //定义参数
    NavigationParameters parameters = new NavigationParameters();
    parameters.Add("Title", "我是导航A");
    //像目标 name 传递参数
    this.regionManager.Regions["ContentRegion"].RequestNavigate(name,parameters);
}

(2)接收参数

导航项目新增模块类,实现INavigationAware接口。
class PageAViewModel : BindableBase, INavigationAware
{
    public PageAViewModel()
    {

    }

    private string title;
    public string Title
    {
        get { return title; }
        set { title = value; RaisePropertyChanged(); }
    }

   //是否重用当前实例
   public bool IsNavigationTarget(NavigationContext navigationContext)
   {
       return false;
   }

   //在当前的页面导航到其他页面的时候发生,可以用于拦截导航。
   public void OnNavigatedFrom(NavigationContext navigationContext)
   {

   }

   //导航完成前, 此处可以处理传递过来的参数以及是否允许导航等。
   public void OnNavigatedTo(NavigationContext navigationContext)
   {
       //三种方式
       if (navigationContext.Parameters.ContainsKey("Title"))
           Title = navigationContext.Parameters.GetValue<string>("Title"); 
   }
}

PageA页面:<TextBlock Text="{Binding Title}" FontSize="60"/>

(3)导航确认和拦截

实现接口由INavigationAware->IConfirmNavigationRequest(其派生于INavigationAware,有委托类型的回调函数),并实现ConfirmNavigationRequest方法
class PageAViewModel : BindableBase, IConfirmNavigationRequest
{
    //导航确认,
    public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
    {
        bool result = true;
        if (MessageBox.Show("是否允许进入此页面?", "确认", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
        {
            result = false;
        }
        // 是否允许下一步进入某个页面**********
        continuationCallback(result);
    }
    
    实现其他如IsNavigationTarget等方法
    ......
}
从当前页面跳转到其他页面时发生,如从PageA跳转到PageB,执行顺序: (A)RequestNavigate->ConfirmNavigationRequest->OnNavigatedFrom->(B)IsNavigationTarget->PageBViewModel(若重用实列)->OnNavigatedTo

(4)导航日志

声明一个IRegionNavigationJournal,它包含导航日志相关的API。

RequestNavigate中有一个回调函数,通过这个callback的上下文中的导航服务获取到Journal并赋值给刚声明的IRegionNavigationJournal。
public class MainViewModel : BindableBase
{
    private readonly IRegionManager regionManager;
    private IRegionNavigationJournal journal;
    public DelegateCommand<string> OpenCommand { get; private set; }
    public DelegateCommand BackCommand { get; private set; }
    public DelegateCommand NextCommand { get; private set; }
    public MainViewModel(IRegionManager regionManager)
    {
        OpenCommand = new DelegateCommand<string>(Open);
        BackCommand = new DelegateCommand(Back);
        NextCommand = new DelegateCommand(Next);
        this.regionManager = regionManager;
    }
    
    //GoBack返回(),GoForward()前进,Clear()清空日志
    private void Back()
    {
        if (journal.CanGoBack)
            journal.GoBack();
    }
    
    private void Go()
    {
        if (journal.CanGoForward)
        {
            journal.GoForward();
        }
     }       

    void Open(string name)
    {
        NavigationParameters parameters = new NavigationParameters();
        parameters.Add("Title", name);
        //通过regionManager接口获取当前全局定义的可用区域
        //通过依赖注入的方式动态的往这个区域注入内容
        this.regionManager.Regions["ContentRegion"].RequestNavigate(name, callback =>
        {
            if ((bool)callback.Result)//导航成功
            {
                journal = callback.Context.NavigationService.Journal;//存储导航请求记录
            }
        }, parameters);
    }
}

标签:regionManager,框架,void,private,Prism,导航,public,页面
From: https://www.cnblogs.com/xixi-in-summer/p/17983070

相关文章

  • 在.framework框架下的winfrom中使用Castle.DynamicProxy实现AOP问题小记
    1.需求:为项目中通讯PLC模块实现AOP,实现统一的日志打印,参数校验,方法执行时间统计2.问题:①现有项目没有IOC容器,没法使用部分AOP库的方法注册到IOC,(注:如果要实现IOC对现有代码改动大,并且AOP只是针对部分模块实现)②要在尽量小的代码改动下实现针对以上问题选择使用Castle.DynamicProx......
  • 插件框架
    插件框架plugin.json{ "plugin": [ { "plugid":1000, "plugname":"bpl1.bpl", "remark":"RESTCRUD" }, { "plugid":1001, "plugname":"bpl2.bpl", &qu......
  • 手写web框架
    自定义web框架框架功能"""功能视图用户访问指定url获取数据库数据,并返回到页面"""wsgiref模块#01文件结构"""urls.py 路由与视图函数对应关系views.py 视图函数(后端业务逻辑)templates文件夹 专门用来存储html文件"""#按照功能的不同拆分之后......
  • gin框架路由讲解
     点击关注......
  • 【小记】MSMF 框架开发 UVC 摄像头如何正确设置 MF_MT_SUBTYPE
    简单说一下:IMFSourceReader有两个可以获取 IMFMediaType对象的接口,分别是 GetNativeMediaType与 GetCurrentMediaType。初始化时调用 GetCurrentMediaType获得的IMFMediaType对象(此时为硬件默认情况下自动选择的对象)再进行修改是不能用于SetCurrentMediaType的,即......
  • jax框架为例:求hession矩阵时前后向模式的自动求导的性能差别
    注意:本文相关基础知识不介绍。给出代码:fromjaximportjacfwd,jacrevimportjax.numpyasjnpdefhessian_1(f):returnjacfwd(jacrev(f))defhessian_2(f):returnjacfwd(jacfwd(f))defhessian_3(f):returnjacrev(jacfwd(f))defhessian_4(f):......
  • 搞起来,使用 SpringBoot 框架徒手撸一个安全、可靠的本地缓存工具
    在实现本地缓存的时候,我们经常使用线程安全的ConcurrentHashMap来暂存数据,然后加上SpringBoot自带的@Scheduled定时刷新缓存。虽然这样可以实现本地缓存,但既不优雅也不安全。那看一下我的思路,首先看一张图!1.每个处理器都有缓存名字、描述信息、缓存初始化顺序等信息,所以应该定义一......
  • 接口自动化框架设计漫谈V1.0
    你好,我是刚哥。针对“pytest搭建接口自动化框架”,谈谈对框架设计的当前认知。简约至上。选择pytest就是选择Python,Python的设计理念是Simpleisbetterthancomplex,不能让初学者直接上手的框架设计,都是在反其道而行之。所谓具备编程思想的自动化框架,并不值得追求。原生用法。B......
  • gin框架路由讲解
    gin框架路由讲解点击关注......
  • Camera基础(Linux之V4L2驱动框架)
    摄像头的基本工作原理如图所示,一个景象的反射光被镜头所捕捉(镜头的光圈可以调节进光量,马达用来调节对焦),最终将聚焦好的图像精准对焦到图片传感器上边(色彩滤波会产生三基色),光信号转化为数字信号,通过模数转换最终得到原始码流数据。问题:那我们可以直接使用这个包含图像信息和颜色信......