wpf: Prism框架(2)区域,模块化



(一)Prism的区域


引用上篇的代码

ViewModel这段代码虽然能完成功能,但是有下面的缺点:

1。 viewmodel里加入太多的控制代码,你Ui如果复杂点,会变成到处都是binding,造成viewmodel中的代码维护越来越复杂。

2。Open中那个丑陋的switch,让人想到为啥它不是依赖注入呢?


   public class MainWindowViewModel : BindableBase
   {
       public DelegateCommand<string> OpenCommand { get;private set; }



       private string _title = "Prism Application33";
       public string Title
       {
           get { return _title; }
           set { SetProperty(ref _title, value); }
       }

       private object body;
       public object Body
       {
           get { return body; }
           set
           {
               //body= value;
               //RaisePropertyChanged();
               SetProperty(ref body, value);
           }
       }

       public MainWindowViewModel()
       {
           OpenCommand = new DelegateCommand<string>(Open);
       }

       private void Open(string obj)
       {
           switch(obj)
           {
               case "ViewA":
                   Body = new ViewA();
                   break;
               case "ViewB":
                   Body = new ViewB();
                   break;
               case "ViewC":
                   Body = new ViewC();
                   break;
           }
       }
   }


可以使用Prism的区域功能来简化上面的过程:

(一)MainWindowViewModel的变化

我们取消了原来的Body,采用依赖注入的方式,用构造函数的DI方式注入IRegionManager

在app.xmal.cs代码中,我们会往容器内添加三个View:ViewA,ViewB,ViewC

我们看到现在的代码就不再需要费力的去用代码维护view的binding。

而且更重要的是,在后面的例子里,ViewA这样的View可以是另一个项目的,也就是说可以跨项目模块化调用。

private readonly IRegionManager regionManager;
public MainWindowViewModel(IRegionManager region)
{
	OpenCommand = new DelegateCommand<string>(Open);
	this.regionManager = region;
}
private void Open(string obj)
{
	//首先通过IRegionManager接口获取全局定义的可用区域
	//往这个区域动态的去设置内容,方式是使用依赖注入
	this.regionManager.Regions["ContentRegion"].RequestNavigate(obj);
}

(二)app.xmal.cs代码的变化

往容器内添加三个View:ViewA,ViewB,ViewC

		protected override void RegisterTypes(IContainerRegistry containerRegistry)
		{
			containerRegistry.RegisterForNavigation<ViewA>();
			containerRegistry.RegisterForNavigation<ViewB>();
			containerRegistry.RegisterForNavigation<ViewC>();
		}


(三)MainWindow.xmal的变化

在view中定义一个区域,并命名为ContentRegion。

在第(一)步的Open函数中,会用到这个区域的命名。

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


源代码:

链接:https://pan.baidu.com/s/1ldo23MdBBs8zLJNTz-MmWg 

提取码:e98u 

--来自百度网盘超级会员V6勇哥的分享



(二)Prism的模块化

把ViewA,B,C放到独立的项目里去,利用override方法ConfigureModuleCatalog添加三个模块。

有两种方式,一是要引用三个模块的命名空间,二是不用引用,直接动态读取指定目录下的模块。

现在介绍第一种方法:


创建三个wpf类库项目

引用Prism.DryIoc。

创建View目录,创建wpf用户控件ViewA,在其xaml里放入TextBlock,这个跟之前一样。

唯一不同的是,我们要创建一个类,名称任意,它用来标识这是一个模块。

image.png

这个类的内容如下:

就是要继承IModule,我们只用实现它的RegisterTypes

using Prism.Ioc;
using Prism.Modularity;

namespace ModuleA.View
{
	public class ModuleAProfile : IModule
	{
		public void OnInitialized(IContainerProvider containerProvider)
		{
			//throw new NotImplementedException();
		}

		public void RegisterTypes(IContainerRegistry containerRegistry)
		{
			containerRegistry.RegisterForNavigation<ViewA>();
		}
	}

}

MainWindowViewModel不做任何变化。


App.xaml.cs变化如下:

  1.   去掉之前在RegisterTypes里写的依赖注入的容器内容

  2.  ConfigureModuleCatalog方法里添加三个模块的标识模块的类

using FullApp1.Modules.ModuleName;
using FullApp1.Services;
using FullApp1.Services.Interfaces;
using FullApp1.Views;
using ModuleA.View;
using ModuleB.View;
using ModuleC.View;
using Prism.Ioc;
using Prism.Modularity;
using System.Windows;

namespace FullApp1
{
	/// <summary>
	/// Interaction logic for App.xaml
	/// </summary>
	public partial class App
	{
		protected override Window CreateShell()
		{
			return Container.Resolve<MainWindow>();
		}

		protected override void RegisterTypes(IContainerRegistry containerRegistry)
		{

		}

		protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
		{
			moduleCatalog.AddModule<ModuleAProfile>();
			moduleCatalog.AddModule<ModuleBProfile>();
			moduleCatalog.AddModule<ModuleCProfile>();
		}
	}
}


源代码:

链接:https://pan.baidu.com/s/1gBTWSV6c0xFUovCMsgt8jw

提取码:k974 

--来自百度网盘超级会员V6勇哥的分享



第二种方法:

App.xaml.cs变化如下:

设置模块目录为当前exe的目录下的Modules下。

		protected override IModuleCatalog CreateModuleCatalog()
		{
			return new DirectoryModuleCatalog()
			{
				ModulePath = @".\Modules"
			};
		}

其它代码不用变化。


为了方便把三个模块的dll都输出到这个目录,可以设置编译完成后的事件:

copy "$(ProjectDir)bin\Debug\net6.0-windows7.0\$(ProjectName).dll" "$(SolutionDir)FullApp1\bin\Debug\net6.0-windows\Modules\$(ProjectName).dll"

如果这个路径有问题,可以查看vs输出窗口显示的错误路径串,改正后即可。

image.png


第二种方式不需要程序强引用三个模块的命名空间。它和三个模块之间是完全没有耦合。


源码下载:

链接:https://pan.baidu.com/s/1GrFPyF90uhbZ5SfeVsalFA 

提取码:pikt 

--来自百度网盘超级会员V6勇哥的分享


prism还提供配置文件载入模块,xml方式载入等。

详细请参考github上的示例代码:https://github.com/PrismLibrary/Prism-Samples-Wpf

image.png



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2024-06-12 21:30:09 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864