博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Silverlight]用Prism打造自己的程序开发架构
阅读量:7195 次
发布时间:2019-06-29

本文共 4072 字,大约阅读时间需要 13 分钟。

    大家都知道Prism自带的StockTraderRI的例子,这个例子给我们展示了由不同的功能模块(包括里面的页面)组合成主界面(shell)的方法;我当初看到这个例子总觉得怪怪的,原因是我的项目经验中基本没有出现过这样的需求,而出现最多的是“在主界面中显示(调用)不同的模块中的页面”:例如我在主界面有个菜单,如图:

1、我想在点击某个菜单项的时候将某个模块中的某个页面显示在主界面菜单下面的的内容区,而且要有显示的动画效果,如图:

这个动画效果不太好截图,其实是通过向左滑动来切换页面,大家下载代码看看就明白了,

2、各个模块都要按需加载,模块加载过程中要有进度显示,如图:

3、全部采用MVVM设计。

我想可能也有其他人有过我这样的困惑,所以为了让大家少走弯路,少造轮子,就有了这篇随笔,让我们不再困惑于StockTraderRI的那个例子,实现更适合自己项目的程序开发框架。

我的项目结构如图:

PrismDemoMain是主Silverlight程序,PrismDemoMain.Web用来宿主主程序;

PrimDemoCommon是Silverlight类库,提供给主程序和各个模块项目用来引用(提供公共对象)。
Modules解决方案文件夹下面的两个项目ModuleA和ModuleB是分别对应两个模块ModuleA和ModuleB,例如ModuleA的对象代码如下:

using
 System;
using
 Microsoft.Practices.Prism.Modularity;
using
 Microsoft.Practices.Prism.MefExtensions.Modularity;
using
 System.ComponentModel.Composition;
using
 PrismDemoCommon;
namespace
 ModuleA
{
    [ModuleExport(
typeof
(ModuleA))]
    
public
 
class
 ModuleA : IModule
    {
        
public
 
void
 Initialize()
        {
            
//
throw new NotImplementedException();
        }
    }
}

 by the way,我个人更喜欢用MEF,Prism中我也只用MEF的那个扩展,例如MefBootstrapper等,甚至有点讨厌unity那个,可能是代码洁癖的原因吧,其实整个程序都可以用MEF来管理对象的初始化,杜绝new object代码,可以参照我随笔中的代码。

ModuleA项目中包含两个文件夹Views和Viewmodels,这两个文件夹各放什么大家都知道;值得一提的是,我将Views中的各个View分成两类,一类是MainView,继承自IMainView接口,另一类则不用继承这个接口,MainView是用来显示在主界面内容区的View,继承自IMainView也是为了能在主界面内容区显示方便,而其他View则是被MainView调用的View。

ModuleA中的View1的代码如下:

using
 System;
using
 System.Collections.Generic;
using
 System.Linq;
using
 System.Net;
using
 System.Windows;
using
 System.Windows.Controls;
using
 System.Windows.Documents;
using
 System.Windows.Input;
using
 System.Windows.Media;
using
 System.Windows.Media.Animation;
using
 System.Windows.Shapes;
using
 System.ComponentModel.Composition;
using
 ModuleA.ViewModels;
using
 PrismDemoCommon;
namespace
 ModuleA.Views
{
    [Export(
"
ModuleA$View1
"
typeof
(IMainView))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    
public
 
partial
 
class
 View1 : UserControl,IMainView
    {
        [ImportingConstructor]
        
public
 View1(ViewModel1 viewModel)
        {
            InitializeComponent();
            
this
.DataContext 
=
 viewModel;
        }
      
    }
}

看一下模块ModulesCatalog.xaml文件,很简单。

<
Modularity:ModuleCatalog 
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
                          xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
 
                          xmlns:sys
="clr-namespace:System;assembly=mscorlib"
 
                          xmlns:Modularity
="clr-namespace:Microsoft.Practices.Prism.Modularity;assembly=Microsoft.Practices.Prism"
>
    
<!--
 Module info without a group 
-->
    
<
Modularity:ModuleInfo 
Ref
="ModuleA.xap"
 ModuleName
="ModuleA"
 ModuleType
="ModuleA.ModuleA, ModuleA"
 InitializationMode
="OnDemand"
 
/>
    
<
Modularity:ModuleInfo 
Ref
="ModuleB.xap"
 ModuleName
="ModuleB"
 ModuleType
="ModuleB.ModuleB, ModuleB"
 InitializationMode
="OnDemand"
 
/>
</
Modularity:ModuleCatalog
>

PrismDemoMain主程序中有个MainPageModule的文件夹,其实里面也是一个Prism的模块,是该程序真正的主界面实现,采用View注入到shell中,shell中就一行代码:

<
ContentControl 
regions:RegionManager.RegionName
="MainPageRegion"
  HorizontalContentAlignment
="Stretch"
 VerticalContentAlignment
="Stretch"
 
/>

这样做的好处是,假如我对这个主界面不满意,我可以方便的用其他的MainPageModule来替换这个,甚至可以做成多个主界面供用户选择。

载入模块,显示页面,动画效果等都是在这个模块完成的,例如点击菜单显示切换视图的代码如下:

 
private
 
void
 ShowCurrentMainView()
        {
            
//
取得当前主视图的实例
            IMainView mainView 
=
 ServiceLocator.Current.GetInstance
<
IMainView
>
(currentMainViewName);
            
if
 (mainView 
!=
 
null
)
            {
                eventAggregator.GetEvent
<
ShowMainViewEvent
>
().Publish(mainView);
            }
        }
        
private
 
void
 ActiveView(
object
 obj)
        {
            
string
 mainViewName 
=
 obj.ToString();
            
//
如果当前视图就是要激活的视图,则返回
            
if
 (currentMainViewName 
==
 mainViewName) 
return
;
            currentMainViewName 
=
 mainViewName;
            
//
获取激活该视图需要的模块名称。
            
string
 moduleName 
=
 currentMainViewName.Substring(
0
, currentMainViewName.IndexOf(
"
$
"
));
            
//
初始化ModuleManager,加载事件等
            InitializeModuleManager();
            
//
根据模块名取得模块信息
            ModuleCatalog moduleCatalog 
=
 ServiceLocator.Current.GetInstance
<
ModuleCatalog
>
();
            
if
 (moduleCatalog 
==
 
null
return
;
            ModuleInfo moduleInfo 
=
 moduleCatalog.Modules.FirstOrDefault(p 
=>
 p.ModuleName 
==
 moduleName);
            
if
 (moduleInfo 
==
 
null
return
;
            
//
判断模块是否已经初始化
            
if
 (moduleInfo.State 
==
 ModuleState.Initialized)
            {
                
//
显示当前主视图
                ShowCurrentMainView();
            }
            
else
 
if
 (moduleManager 
!=
 
null
)
            {
                moduleManager.LoadModule(moduleName);
            }
        }

引发显示主视图的事件,并动画显示主视图,请参考源代码。

转载地址:http://uqvkm.baihongyu.com/

你可能感兴趣的文章
Python之禅及释义
查看>>
laravel5.4 开发简书网站
查看>>
设置类库项目的程序集名称和默认命名空间
查看>>
对属性NaN的理解纠正和对Number.isNaN() 、isNaN()方法的辨析
查看>>
【转】iOS lame编译 arm64 armv7s armv7 x86_64 i386指令集
查看>>
LeetCode-二叉树的最大深度
查看>>
Linux内核剖析(五)Linux内核的构建过程
查看>>
19、生鲜电商平台-安全设计与架构
查看>>
webpack常见的配置总结 ---只是一些常见的配置
查看>>
Django_06_项目完成
查看>>
寻找子字符串int find_substr(char *s1, char *s2)
查看>>
apache配置文件参数优化
查看>>
Manifest.xml中不要出现重复的uses-permission声明
查看>>
UFS文件系统简明学习笔记
查看>>
详解Redis 的持久化机制--RDB和AOF
查看>>
就算神游 之四:富士山和富士游乐园 9
查看>>
linux 学习 12 服务管理
查看>>
maven全局配置文件settings.xml详解
查看>>
模型图纸数据库设计
查看>>
Two classes have the same XML type name 排错【转】
查看>>