微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Prism学习之一 综合介绍



Prism 简介

分类 Prism 405人阅读 评论(0) 收藏 举报

Prism 简介

Prism 是一种应用于silverlight的设计模式, 代码和教学文档可以从官网下http://compositewpf.codeplex.com/ 最新的应该是Prism4,安装后会在电脑里面生产一个文件包,里面有SampleCode和Prism的lib dll文件以及一个教学的文档。

Prism的自带的教学文档比较抽象,把一些主要的思想提炼了出来,但没有做到step by step,我想写这么一个学习博客来鼓励自己学习,同时分享下学习经验吧。

官网的文档里有Prism的定义和介绍,我就不重复了,我对Prism的理解是,随着软件开发发展,开发员越来越希望把前台显示后台逻辑分开,传统的.net实现方法前台用aspx文件写,后台用cs文件,但是这样还不够!

比如说在前台加入一个button,后台实现button的click事件:  

  <asp:Button ID="btnSave" runat="server" Text="Save" onclick="btnSave_Click" />

     protected void btnSave_Click(object sender,EventArgs e)
     {
           
     }

现在的开发者依然觉得这样还没有实现完全的 loosely-coupled,前后台依然被“btnSave_Click”这个方法名束缚住了。我们期望的是可以把前台交给一个美工,后台交给一个程序员,美工制作页面的时候完全不用关心逻辑方面的问题,只要把画好的页面丢给后台程序员,后台程序员也不用管前台页面里的那些控件取的什么名字,写完自己逻辑代码以后,再写一个viewmodel的文件,把前台的xaml文件和自己的逻辑代码一绑定,job done!分工明确。Prism还有一个优点就是module开发模式,一般来说一张web页面总能分成好几块,比如上方有导航模块,主模块可以分成正文模块,统计chart模块,calendar模块,地图模块等等,Prism可以允许把这些模块交给不同的人去做,完成后拼成一张页面,这对模块重用也很有帮助,听起来是不是很爽阿!

不过在爽之前还有很多东西要学!慢慢来吧。

    

prism4学习笔记一:基础知识

分类 Prism 625人阅读 评论(0) 收藏 举报
 

第一:prism是个啥玩意?
        一个水平差点的泥瓦匠只能砌一个厕所,一个好点泥瓦匠可以独立砌一个平房,但再大点的工程可能就不可能单兵作战了,分工协作就必须了,看现在建造商品房的速度就知道了,都是先浇注好水泥框架,然后泥瓦匠砌墙粉刷,水电工后面跟上,如果不是这种框架设计,这种速度是做不到的。建房子如此,写程序也是如此;
       prisam是最优秀的wpf/silverlight应用程序开发框架之一,使用它可以达到:界面和逻辑剥离、程序开发的模块化、并行开发加快开发速度,程序的扩张性和可维护性更强。我们使用框架就是为了让我们的开发项目更加受控,所以用不用框架由你的项目决定,就好比我们搭建一个狗窝也可用采用框架结构,不过现实中可能没有人这样干。
       无论用不用,反正学习和领悟一下人间的思想总之是没有坏处的;

第二:prism如何安装?
step 1:到微软下载http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3453ab2b-2067-41e4-b087-312d8385cf1b&displaylang=en
Step 2: install System Requirements .net framework 4.0  vs2010  microsoft silverlight 4 tools for vs2010
Step 3: Extract the Prism Source Code,Binaries,and Documentation
Step 4: Register the Prism Library Binaries with Visual Studio
这些类库在解压路径的bin目录下,按开发程序类别分成desktop、silverlight、phone,你开发不同类别的程序就需引用不同的dll文件


第三:prism基本架构
       解压后的prism文件夹,你看见的就是一堆的文件,首先你需要找到的文件是Prism4.chm,它负责引导你了解prism,都是E文,但至少关于prism的几大部分说明要看懂。
    shell:顶级窗口,就像一个空空荡荡的舞台,shell本身不包含内容,他的功能都是通过module来是实现;
    bootstrapper:应用程序的入口点,就像一个工厂的调度,这家伙要完成很多的协调事情;
    region内容区域:类似一个占位符,先把茅坑占了,至于上面蹲的人是可以换的;
    module:真正实现业务功能的东西,是View、数据、模型组成的集合;一个应用程序中可以根据复杂程度分厂很多module;
       用一个电影院来举个例子:shell就是一个剧院,里面空荡荡的演出厅就是region;bootstrapper就是剧场的运营部门,安排演出单位的引入和演出安排及演出厅之间的资源协调;module就是各个演出剧,例子再形象也只是帮助你去理解,所以我们还是需要仔细看一下架构图。


prism4学习笔记二:应用框架完成你的第一个prisam程序


分类 Prism 505人阅读 评论(0) 收藏 举报

      在开始之前,我们还是先看一下prism创建程序的过程图,有道是一图胜千言:



        看了终归会有点了解,但是如果从没有接触过那还是没有实际的概念。在这个时候千万不要去通读prism4.htm文件,先找到附录里面的动手实验,按着那个做一遍,大概13步:
——————————————————————————————————————————————————————
1.创建一个silverlight项目;
2.添加项目对Microsoft.Practices.Prism.dll/Microsoft.Practices.Prism.UnityExtensions.dll./Microsoft.Practices.Unity.Silverlight.dll/Microsoft.Practices.ServiceLocation.dll的引用
3.添加shell:就将系统认的mainpage.xaml文件重命名为shell,记住.cs文件里面的类名一并修改了;
4.在shell.xaml中添加一个region:<itemcontrol name="mainregion" regions:regionmanager.regionname="mainregion"/>,region的xlm名称空间要先引用xmlns:Regions="http://www.codeplex.com/prism"

5.添加一个继承自unitybootstrapper的bootstrapper类,引入prism框架dll,覆写createshell,Initializeshell,Configuremodulecatalog;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.UnityExtensions;
using Microsoft.Practices.Unity;
protected override DependencyObject CreateShell()
{
    return Container.Resolve<Shell>();//用shell创建一个实例
}
protected override void InitializeShell()
{
    base.InitializeShell();
    Application.Current.RootVisual = (UIElement)this.Shell;//shell接管了主页面
}
protected override void ConfigureModuleCatalog()
{
    base.ConfigureModuleCatalog();//将来总调度就在这里注册模块的
}
6.修改app.xaml,指向bootstrapper
private void Application_Startup(object sender,StartupEventArgs e)
{
    Bootstrapper bootstrapper= new Bootstrapper();
    bootstrapper.Run();
}
至此F5运行,我们可以看见一个空的页面,因为我们只创建了一个空的容器;还没有用module来实现一些功能
7.继续创建一个新项目:silverlight类库,添加其对microsoft.practices.prism.modularity的引用;
8.将新项目中认的class1.cs修改为你需要的类名,比如hellwowordmodule,并使之继承于imodule,同样需要引用using Microsoft.Practices.Prism.Modularity;最后还要添加一个空的Initialize方法
9.按结构添加 views/services/controllers等文件夹,只是意思一下,你可以添加也可以不添加,只要你明白真正的含义就是了;
10.接下来将这个类库加载到应用程序,因为这个module是要被主程序调用的,在你的silverlight项目中添加对这个类库的引用;
11.最后翻过去改bootstripper的configuremodulecatalog方法,实现在实例中注册module,注册有好多方法,动态的、静态的、xml文件的、xaml文件的,先不管这些,闭着眼跟在说明书走;我们前一节举例剧场的时候,说到过运营部门,下面的这个注册就相当于签了几份合同:张学友演出、程冠希演出、....,然后登出了广告海报。
protected override void ConfigureModuleCatalog()
{
    base.ConfigureModuleCatalog();
    ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
    moduleCatalog.AddModule(typeof(HelloWorldModule.HelloWorldModule));
}
12.在views目录下添加一个silverlight控件,上面随便写点东西,比如:我是一只小小鸟。
13.打开类库中的hellwowordmodule.cs,添加一个构造函数,并在其Initiallize方法中使用RegisterViewWithRegion方法将helloworldview返回的内容注册到mainregion中;
  using Microsoft.Practices.Prism.Regions;
private readonly IRegionManager regionManager;
public HelloWorldModule(IRegionManager regionManager)
{
  this.regionManager = regionManager;
}
public void Initialize()
{
    regionManager.RegisterViewWithRegion("MainRegion",typeof(Views.HelloWorldView));
}
————————————————————————————————————————————————————

        最后运行程序我们可以看到结果:我是一只小小鸟。如果你鸟毛没见一根,就得回去一步一步检查你的程序了。
        但凡只要你成功动手做一遍,基本上就了解使用prisma框架开发的流程和他的原理,剩下来的就是专研,每天诵读prism4.htm10遍,另外把压缩包中的那几个帮助文档看一遍,权当学习英语了。
       手动实验做完后,我们就梳理一下这个实例,自己去总结出三大步:
          1.如何实现Bootstrapper的接管和shell的加载,建造出一个影剧院(shell),并建立剧场(region);
          2.如何通过Bootstarpper中重写InitializeModules方法加载Module:引入了各种演出剧目(module);
          3.如何实现module中的view和region建立关系,也就是那个剧目在那个剧场演出?这个是在每个module中实现IModule接口的Initialize方法,在其中通过regionManager.RegisterViewWithRegion方法来完成region和module view的mapping关系。

Prism之Bootstrapper


分类 Prism 541人阅读 评论(0) 收藏 举报
    在程序中使用框架必然要有一个切入点,框架会在这里进行初始化,处理相关配置信息等。在Prism中扮演这一角色的就是Bootstrapper。

      Prism提供了一个抽象基类Bootstrapper,这个类里面包含了包含了许多空的虚方法,可以重写它们添加自己的逻辑。这个基类与任何容器无关,所以可以通过继承它来实现基于特定容器的Bootstrapper,不过通常我们大可不必这样做,因为Prism认提供了两个基于特定容器的Bootstrapper——UnityBootstrapper和MefBootstrapper,分别使用Unity和Mef来实现依赖注入。而我们需要做的工作就是在这两个类之间选择一个适合自己的,稍微配置一下就可以了。当然如果你不喜欢这两个容器或者已有的程序使用了其它容器(如Spring.Net, Castle等),也可以通过继承Boostrapper抽象基类来实现自己的SpringBootstrapper和CastleBootstrapper。虽然UnityBootstrapper的代码看起来挺简单的,但是如果仿照这个来实现CastleBootstrapper却并不是那么容易的一件事(不信你可以试试),所以更好的办法是用现成的。

      那么Bootstrapper都做了些什么呢?

      1. 创建Logger:

      执行CreateLogger方法认创建一个EmptyLogger,不会在任何地方输出log。当然是可以扩展的,比如你可以使用Clog来做一个适配器。

      2. 创建并配置ModuleCatalog

      执行CreateModuleCatalog方法认创建一个空的ModuleCatalog。然后执行ConfigureModuleCatalog方法认情况下这个方法是空的。可以重写这两个方法,加入自定义获取ModuleCatalog的逻辑,比如在CreateModuleCatalog中可以从一个xaml文件中读取Module信息。

protected override IModuleCatalog CreateModuleCatalog()
{    
    return ModuleCatalog.CreateFromXaml(new Uri("/AssemblyName;component/ModulesCatalog.xaml",UriKind.Relative));
}

      3. 创建并配置依赖注入容器

      Prism中使用依赖注入来管理各个组件,你可以使用任何你熟悉的容器,比如Castle,Unity等。Prism中内置了对Unity以及Mef的支持,所以有两种预定义好的Bootstrapper: UnityBootstrapper和MefBootstrapper,其中分别采用UnityContainer和CompositionContainer作为依赖注入容器。以UnityBootstrapper为例,在这一步中会先调用CreateContainer方法,返回一个UnityContainer;然后调用ConfigureContainer方法在这方法中主要是将一些常用的类注册到容器中。

      4. 配置认的Region适配器映射

      为了使xaml中的UI控件可以使用Region,需要先注册一下。Prism支持Region的控件类型有:TabControl,Selector,ItemsControl,ContentControl。当然你也可以通过实现Iregionadapter接口或者直接继承regionadapterBase<T>来使其它控件也支持Region。

      5. 配置认的Region 行为(Behavior)

      为RegionBehaviorFactory添加一些认的行为。这样可以扩展Region的行为。可以通过实现IRegionBehavior接口或继承RegionBehavior来自定义Region的行为,并重写ConfigureDefaultRegionBehaviors方法添加到Region。

      6. 注册框架异常类型

      Prism提供了ExceptionExtensions类来帮助开发人员定位异常发生的根异常。在这一步通过调用RegisterFrameworkExceptionTypes方法向ExceptionExtensions中添加新的Root Exception。

      7. 创建并初始化Shell

      首先调用CreateShell方法来创建一个Shell,这是一个抽象方法,通常这个方法中就是返回作为整个网站容器的页面。之后会将RegionManager attach到Shell上,然后更新定义的Regions,最后调用InitializeShell方法来初始化Shell。认情况下这是个空方法,可以通过重写这个方法加入自定义的逻辑,可以在这方法中将Shell作为Silverlight程序的根容器页面显示出来。

protected override void InitializeShell()
{
    Application.Current.RootVisual = Shell;
}

      8. 初始化Modules

      调用InitializeModules方法,实际上就是调用ModuleManager.Run方法,会调用ModuleCatalog中的所有InitializationMode为WhenAvailable的Module的Initialize方法

      至此,整个容器的初始化过程就完毕了。

      值得一提的还有CommonServiceLocator,这同样是Patterns & Practices小组的产品。它的作用很简单,就是统一依赖注入容器的接口,使程序不必依赖于特定的容器,只需要使用ServiceLocator,然后去间接地使用其它各种各样的容器。在Prism的内部就是使用ServiceLocator来进行管理的。所以不管使用什么样的容器,都需要提供一个实现了IServiceLocator接口的适配器,如使用Unity要提供UnityServiceLocatorAdapter,使用Mef要提供MefServiceLocatorAdapter。这样不管外部使用什么容器,内部都不需要改变。所以如果要使用Prism重头开始构架一个程序,那么在整个程序中不依赖于特定的依赖注入容器接口,而是使用ServiceLocator是一个不错的选择,这样可以在需要的情况下很容易地更换容器,只需要重写一个Bootstrapper和一个ServiceLocatorAdapter就可以了。


Prism简介 Prism之Region


分类 Prism 537人阅读 评论(0) 收藏 举报
 

private void Application_Startup(object sender,StartupEventArgs e) { PrismStarterBootstrapper bootstrapper = new PrismStarterBootstrapper(); bootstrapper.Run(); }
运行程序,结果如下:

imageimageimageimageprism,Prism简介

下面简单介绍一下这个小例子中涉及到的一些概念。
Bootstrapper: 在程序中使用框架需要找到一个切入点,将框架植入进去,将一部分功能委托给框架来实现。在Silverlight中使用Prism的切入点就是App.xaml.cs中的Application_Startup方法。一般来说,这个方法中只是指定页面最先加载的页面,但是我们把认的逻辑去掉,取而代之的是Bootstrapper(在本例中就是PrismStarterBootstrapper)。当调用Bootstrapper.Run方法时,它会完成一些准备工作,如一些配置等。因此你会发现,使用Prism后,启动程序时会比正常启动要慢一些,就是因为Bootstrapper做了许多工作。
Container: 依赖注入容器。在程序中使用依赖注入的好处到处都可以找的到。在Silverlight中使用容器来管理各个组件的一个很明显的好处就是使用单例来降低内存使用。否则每次加载一个页面都需要重新创建一个也很耗费资源的。当然好处不只这些,通过容器来注入一些服务(如本例中的IRegionManager和ITextProvider)显得相当方便。
Module: Prism帮助我们把程序分解成一个功能模块,这些功能模块就叫做Module,通常一个工程就是一个Module。由于Module彼此是独立的,但是在运行时需要将它们整合到一起,因此Prism需要知道Module的存在,这里就涉及到了ModuleCatalog,ModuleCatalog就是Module的容器,里面包含了所有Module的信息,以ModuleInfo的形式存在。ModuleInfo就是对Module的抽象,包含Module的名字,类型,依赖等一些信息。
Shell: 相当于程序的入口,初始界面,还能够提供类似ASP.Net中的母版页的功能。Shell必须由Bootstrapper创建,因为Shell需要使用的一些service,比如RegionManager等,需要在Shell显示注册
Region: 相当于ASP.Net中的ContentPlaceHolder(是这么叫的吧?),起到占位符的作用,如本例中Shell中有两个Region——RegionA和RegionB,定义了两块区域。在Module的初始化过程中,通过IRegionManager将Module中的页面放进了定义好的Region中。IRegionManager负责管理Region,可以通过它向Region中注册View,进行导航等。
Prism的功能当然远不止这么简单,它还提供对MVVM模式的支持,对导航的支持等,在后续文章中会逐步介绍。希望能够通过本文让大家对Prism有一定的了解。

 

Prism之Region

Prism可以帮助我们开发模块化程序,将程序分割成一个个独立的public class ActionControllerviewmodel : NotificationObject { private IRegion _demoshowRegion; public bool CanGoBack { get { return _demoshowRegion.NavigationService.Journal.CanGoBack; } } public bool CanGoForward { get { return _demoshowRegion.NavigationService.Journal.CanGoForward; } } void ToPrevIoUs() { _demoshowRegion.NavigationService.Journal.GoBack(); ResetNavigationButtonState(); } void ToNext() { _demoshowRegion.NavigationService.Journal.GoForward(); ResetNavigationButtonState(); } void ResetNavigationButtonState() { RaisePropertyChanged(() => this.CanGoBack); RaisePropertyChanged(() => this.CanGoForward); } }

imageimage1-30-20111-30-2011imageprism,Prism之Region(1)

导航API还可以控制视图的生命周期,在页面跳转时进行确认拦截(Confirming or Cancelling Navigation)以及其它功能,可以参考 Developer’s Guide to Microsoft Prism。

module4,Prism 4学习笔记之Module


分类 Prism 418人阅读 评论(0) 收藏 举报
 

在开发过程中将程序分解,使其变成一个个独立的模块,有助于代码的复用,也提高了可维护性。并且可以由多人协同工作,各自开发不同的模块,最后组装到一起,这样也大大提高了生产率。
Prism中有Module这个概念,通过将程序分解为一个个Module,并采用一种松散耦合的方式来将它们组合到一起,可以达到使程序更加灵活、易于测试、易于维护等目的。
下面先看一下两个非常重要的概念:

Modules: Modules指可以独立开发、测试、部署的功能的集合。在许多情况下,会由不同的小组分别来开发和维护不同的Module。典型的基于Prism的应用就是由多个module组合而成。Module也可以用来指代特定的业务(譬如资料管理),并且将所有的视图、Service、以及所需的数据模型封装起来以实现该功能。Modules也可以用来封装一般的应用程序底层架构或者服务(例如日志和异常管理服务),以达到在多个应用中复用的目的。
ModuleCatalog: 在一个组合式应用中,宿主程序必须能够动态地找到并加载模块(modules)。在Prism中,module catalog可以用来指定哪些模块需要加载,需要在什么时候以什么样的顺序加载。在ModuleManager和ModuleLoader这两个组件中会用到Module catalog, 它们是用来下载Module(远程应用中),然后将Module所在的程序集加载进应用中并进行初始化。Prism允许以多种方式来定义module catalog,包括使用代码定义,在xaml文件中声明或者放到配置文件中。
每个Module都有一个实现了IModule接口的核心类,这个类的作用就是将其所在的Project标记一个Module,并且会将该Module集成到系统中。IModule接口中只有一个Initialize方法,所有需要完成的工作都需要在该方法中实现。实现了一个Module后,就要在ModuleCatalog中配置该Module,当程序解析ModuleCatalog的时候,就可以根据需要进行Module初始化(也就是调用IModule接口的Initialize方法)。大致过程如下所示:
static void Main(string[] args) { IModuleCatalog moduleCatalog = ModuleCatalog.CreateFromXaml(new Uri("/PrismModuleTest;component/ModuleConfig.xaml",UriKind.Relative)); ILoggerFacade logger = new TextLogger(); IUnityContainer container = new UnityContainer(); IServiceLocator serviceLocator = new UnityServiceLocator(container); IModuleInitializer moduleInitializer = new ModuleInitializer(serviceLocator,logger); IModuleManager moduleManager = new ModuleManager(moduleInitializer,moduleCatalog,logger); PrintState(moduleCatalog.Modules); // 打印一下状态 moduleManager.Run(); PrintState(moduleCatalog.Modules); Console.WriteLine("-------------------------"); moduleManager.LoadModule("ModuleD"); PrintState(moduleCatalog.Modules); }
在运行程序之前,切记要将所有Module编译生成的dll文件拷贝到控制台程序的bin目录下。

再次运行程序。得到的结果和之前一样。

prism4学习笔记6:prism、Mef和Unity、MVVM的关系


分类 Prism 619人阅读 评论(0) 收藏 举报
 

        我们再前面提到了依赖注入,还举了例子好像是网购,你需要东西,就可以送上门来,网购平台就是我们依赖注入的容器,而MEF和unity就好比淘宝、阿里巴巴、易趣网等网上交易平台。你可以选择其中的一种作为容器,当然不同的容器,服务也会有不同。
        把依赖注入,改成依赖(谁?)注入,这个谁就可以是MEF和unit,也还可以是其他可以依赖注入的容器。有了选择就有了比较,你自然就有下面这些疑问:
一.Mef和unity是不是其中一个以绝对优势成功替代另外一个
    在prism里面,Mef和unity例子都是分开做了,所以他们关系就不是谁替代谁的问题了,至少现在不是,如果是替代关系,人家也不用费那么多无用功了。

二.如果不是替代关系,那么他们各自有哪些特长?这个E文:
Some of the capabilities provided by both containers include the following:
       .They both register types with the container.
        .They both register instances with the container.
        .They both imperatively create instances of registered types.
        .They both inject instances of registered types into constructors.
        .They both inject instances of registered types into properties.
        .They both have declarative attributes for marking types and dependencies that need to be managed.
        .They both resolve dependencies in an object graph.
Unity provides several capabilities that MEF does not:
         .It resolves concrete types without registration.
         .It resolves open generics.
         .It uses interception to capture calls to objects and add additional functionality to the target object.
MEF provides several capabilities that Unity does not:

         .It discovers assemblies in a directory.
         .It uses XAP file download and assembly discovery.
         .It recomposes properties and collections as new types are discovered.
         .It automatically exports derived types.
         .It is deployed with the .NET Framework.
至于选择时机,也请看E文:

        Unity is mostly used for static dependencies and is more an “internal” technology,meaning outsiders do not need to kNow that unity is being used in the application.
         MEF should be used for dynamic dependencies,it is grate at dynamically loading components and with the use of attributes it make creating application extensions or an application that can be extended by others easy and streamlined.

       看到了没有,共同点大于差异点。另外要注意一点,MEF是在.net framework里面的,所以对于.net而言 MEF属于“家花”,unity则是“野花”,野花有野花的味,家花有家花的香。


三.从prism到MEF,MVVM,UNITY,一大堆名称把人搞得,这些不都是framework吗?
       举个例子,比如一个武馆,设置好多种拳种的教学,如果你是一个小女子你就选择咏春拳,如果你喜欢刚猛的拳法可以选择八极、洪拳、心意拳,如果你喜欢高深点的就选择太极、八卦、形意.....选好了拳种,是不是就要开练了,武术讲究:内练一口气,外连筋骨皮,练习的时候就要讲究一些要领,瞎来出不了功夫还伤自己。

        将这个套到pirsm上:
         prism就是武馆,提供了一个场地、师资力量、武术器材,有合理的价格,比较完善的服务体系,让你学有所成,学的放心;对于他来说主要是要高效运作,通过这个框架实现程序模块化开发。它是基于应用程序层次的;

         EMF、UNITY就是拳种:是提供依赖注入的容器,你选择咏春拳就给你注入咏春,你选择形意就给你注入形意;是基于模块化组件的;有的武馆有优势的拳种,就好比prism还可以使用其他依赖注入的容器,但是EMF和Unity更优秀些;
         MVVM就是练功的方法:MVVM就是让你可以内外分开练,最后轻松的做到内外合,用这种练功方法效率更高些;MVVM的核心是View的抽象,我们前面说到prism实现页面设计和代码设计的分离,是通过mvvm实现的。
         明白关系了没有,还没有?开个玩笑:那你就是文的不行,武的也不用练,只能去练练健美长几坨肉;

    

prism4学习笔记三:白话mvvm


分类 Prism 443人阅读 评论(1) 收藏 举报
从prism的框架突然扯到了MVVM,一个框架没有讲完又冒出来一个,好像跳开了主题,其实是一点都没有跳开。mvvm是wpf/silverlight程序的主要模式,我们前面说了prism的主要成就之一就是通过模块开发实现并行开发从而加快开发速度,而mvvm也是这个理。 走到大街上你看长发的女人多还是剃光头的女人多?短头发的男人多还是长头发的男人多,答案用脚底板也可以回答,这就说明这个世界上艺术家少啊!假艺术家比程序少,真艺术家那就更少了,市场就得迁就他们。程序员大多是理性思维,所以开发出来的界面就太那个了!指望开发美得像花一样的界面是不现实的,可是一个理性的人和一个感性的艺术家在一起搞一个程序,那有简直......MVVM就是这个目的,把一个页面程序撕成两半,理性部分交给理性的人干,感性的部分交给感性的人去干,两者的关系是一个松耦合的关系,最后两个东西一拼,好绝了。可是有人有疑问:以前我们的页面不是已经分成了两个文件了吗?只能粗粗这么说,那个分的不彻底,MVVM分的更彻底些。 MVVM有这么好,prism这个框架不可能不用,因这个不是prism自有的东西,在她的那个文档中肯定不会很多,所以你还需要跳出那个帮助文档去找点野食吃吃。 MVVM就三大元素:view、model、viewmodel1.view:就是那个xaml文件,负责界面显示,有各种各样的控件和元素,当然还有一小点代码,虽然前面提到了撕成两半,但是打断骨头连着筋,那么一点代码还是需要的的,不过这个不影响我们的艺术家放手工作。也因为代码弱化,所以逻辑的东西也就不再这里实现了,只能显示一下数据。都知道“美人爱傍大款”,view弱的连显示东西通常也靠“绑”。2.model:这个是程序员干的事情,很好理解,不多讲,是实现数据和业务逻辑的。3.modelview:这个玩意是多出来的玩意。到底是个啥玩意,不过仔细想想就明白了,一个艺术家在那里天马行空,一个程序员在那里闭门造车,如果中间没有个东西协调一下,那出来的东西就“银样镴枪头”只能看不能用了。我们讲model和view之间是松耦合关系,那个松就是通过这个modelview实现的。世界上万物都是相同的,界面设计、程序设计都是文人的活,其实武道亦是如此,练武的时候也是要讲究“松”的。不过不是全松,是松了这个紧了那个,能量守恒定律吗。 前面的都是白话,最后用你眼白一下两张图。

Prism4学习笔记4:动手完成一个MVVM实例

分类 Prism 492人阅读 评论(0) 收藏 举报
 我们前面一节白话白眼,都只是从概念上了解了mvvm,了解和做还是差距很大,所以我们同样需要亲自动手实验来真的弄懂mvvm。
       例子就取一个生活中的,用mvvm模式完成家庭的操作,比如显示查询家庭成员,增加家庭成员(娶妻生子等),减少家庭成员(嫁女老去等).
       确定好这个例子我们就需要先准备一下数据,我们首先想到可能是用数据库,不过silverlight是浏览器客户端的东西,是不能和你以前使用asp.net一样主动直接连接数据库的,如果你真的要开始就连接数据库,你还得准备另外学习一些知识。
       我们先构思一下自己的类的样子:
         class familymember
          {
               public string Name{get,set;}//姓名
               public string Sex{get,set;}//性别(不使用bool,因为现在有中性人了)
               public string Title{get,set;}//称谓
               public int    Age{set,get;}//年龄
          }

       然后我们就可以开始工作,打开vs2010 创建一个silverlight应用程序 family.sln.进入设计界面,照着步骤往下,想不明白也别管,到了最后你就完全明白了。
1.在解决方案管理按MVVM的模式新建Views、Models、viewmodels、commands文件,这个不是必须的,但是真正做项目的时候是必须,你的组织你的程序文件啊!否则成百上千的文件,你要找个文件都得找成近视眼;
2.在models文件夹下新建一个类familymember.cs,照抄上面的;
        public class familymember//家庭成员类
        {
             public string Name{get;set;}--姓名
             public string Sex{get;set;}--性别(不使用bool,因为现在有中性人了)
             public string Title{get;set;}--称谓
             public int    Age{set;get;}--年龄
        }
3.继续在models文件下再新建一个类family.cs,当然你可以不另外创建,直接写在familymember.cs里面
         using System.Collections.Generic; //List类在此名称空间下
         public class family//家庭类(就是familymember类的集合)
         public class family
            {
                 private List<familymember> _family;
                 public List<familymember> initfamily()
                     {
                        _family = new List<familymember>()
                           {
                                new familymember{Name="王大爷",Age=120,Sex="男",Title="太爷"},
                                new familymember{Name="王老爷",Age=80,Title="爷爷"},
                                new familymember {Name="王中钱",Age=50,Title="老爸"},
                                new familymember {Name="王夫人",Age=48,Sex="女",Title="老妈"},
                                new familymember {Name ="王大二",Age=25,Title="大儿子"},
                                new familymember {Name="王八蛋",Age=20,Title="小儿子"},
                                new familymember {Name ="王小妹",Age=18,Title="小女儿"}
                           };
                          return _family ;
                  }

               }

4.设计我们的viewmodel文件,在viemodels文件夹下我们新建一个familyviewmodel.cs类
                 public class familymodelview
                 {
                   public List<familymember> myfamily { get; set; }
                   public familymodelview()
                 {
                       //构造函数中初始化家庭成员列表
                       myfamily = new family().initfamily();
                  }
                  }
5.在views下面建一个文件familyview.xaml,这个是用来显示家庭成员的;
        <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDeFinitions >
            <RowDeFinition Height="auto"/>
            <RowDeFinition />
        </Grid.RowDeFinitions>
        <StackPanel Orientation="Horizontal" >
        <TextBlock Text="输入查询条件"/>
        <TextBox Name="txtsearch" Width="100" Height="23"/>
         <Button Name="btnsearch" Content="查询"/>
         <Button Name="btnadd" Content="添加"/>
         <Button Name="btndel" Content="删除"/>
        </StackPanel>
        <sdk:DataGrid Grid.Row="1" Width="300" Name="mygrid" AutoGenerateColumns="False"  ItemsSource="{Binding myfamily}"     HorizontalAlignment="Left" IsReadOnly="True">
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Binding="{Binding Name}" Header="姓名" Width="80"/>
                <sdk:DataGridTextColumn Binding="{Binding Title}" Header="称谓" Width="80"/>
                <sdk:DataGridTextColumn Binding="{Binding Sex}" Header="性别" Width="50"/>
                <sdk:DataGridTextColumn Binding="{Binding Age}" Header="年龄" Width="50"/>
                <sdk:DataGridTemplateColumn x:Name="c1" Header="删除" >
                    <sdk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Name="btndelete" Content="Del" Click="btndelete_Click"/>
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellTemplate>
                </sdk:DataGridTemplateColumn>
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>

    </Grid>
6.开始拼装,在Mainpage.xaml文件中写上
       <Grid x:Name="LayoutRoot" Background="White" >
             <local:familyview/>
        </Grid>
      同时在cs文件中,将mainpage的构造函数修改一下:
       public MainPage()
          {
            InitializeComponent();
            this.LayoutRoot.DataContext = new familymodelview();
          }
7.运行一下,是不是看见了家庭成员列表。比起以前的asp.net开发是不是很繁杂啊,一点都不习惯啊!例子到这里好像还是没有看出太大的端倪,但应该可以看出view文件已经很白了,我们继续往下。

8.现在王小二娶了媳妇董雨进门,那么这个家庭列表就增加了,我们需要添加方法,如果是asp.net,在view.cs文件调用一下解决了,但这样那个xaml文件又复杂了,理性人和感性人又得纠结了。在mvvm中这个要玩的是familymodelview.cs这个文件添加一个addmember方法
      public void addmember(familymember p)
     {
          MessageBox.Show("恭喜,你的家庭成员增加了");
     }

    同时我们把查询删除方法添加上.......
9.方法添加完了,我们需要把这个方法绑定到view里面的添加按钮上,这个时候就需要用到Icommand接口了。在commad下建一个relaycommand.cs
    public class relaycommand:ICommand
      {
        private bool _isenabled;
        private Action _handler;
        public relaycommand(Action handler)
        {
            handler = _handler;
        }
        public bool IsEnabled
        {
            get { return _isenabled; }
            set
            {
                _isenabled = value;
                if (CanExecuteChanged != null)
                {
                    this.CanExecuteChanged(this,EventArgs.Empty);
                }
            }
        }
        public bool CanExecute(object parameter)
        {
            //throw new NotImplementedException();
            return IsEnabled;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            //throw new NotImplementedException();
            _handler();
        }
    }
10.回到familymodelview.cs里面添加上一些语句,完整程序的如下
        public List<familymember> myfamily { get; set; }
        public string searchtext { get; set; }//这个是用于和那个搜索条件绑定用的
        private ICommand _addfamilymembercommand;
        private ICommand _deletefamilymembercommand;
        private ICommand _searchmembercommand;
        public ICommand addfamilymembercommand
        {
            get { return _addfamilymembercommand; }
        }
        public ICommand deletefamilymembercommand
        {
            get { return _deletefamilymembercommand; }
        }
        public ICommand searchmembercommand
        {
            get { return _searchmembercommand; }
        }

        //构造函数
        public familymodelview()
        {
            myfamily = new family().initfamily();
            _searchmembercommand = new relaycommand(searchfamilymember) { IsEnabled = true };
            _addfamilymembercommand = new relaycommand(addfamilymember) { IsEnabled = true };
            _deletefamilymembercommand = new relaycommand(removefamilymember) { IsEnabled = true };
        }
        //实现功能方法
        public void addfamilymember()
        {
            MessageBox.Show("恭喜,你的家庭成员增加了");
        }
        public void removefamilymember()
        {

            MessageBox.Show("sorry,你的家庭成员减少了");
        }
        public void searchfamilymember()
        {
            List<familymember> mylists = null;
            if (!string.IsNullOrEmpty(searchtext))
            {
                mylists = new List<familymember>();
                foreach (familymember p in myfamily)
                {
                    if (p.Name.Contains(searchtext))
                        mylists.Add(p);
                }
                myfamily = mylists;
            }
          
        }
    }
10.这个时候回到view界面,程序再狠,也不可能知道艺术家在xaml文件中发挥到天上还是地上,所以作为程序员的你还需要在多废点脑细胞,谁让你能呢!如果说view是个美人,那viewmodel是view背后的那个男人,view要发挥作用是离不开viewmodel的,在view的cs文件中写上:
      public partial class familyview : UserControl
       {
            familymodelview family1 = new familymodelview();
            public familyview()
             {
                InitializeComponent();

              }

        private void btndelete_Click(object sender,RoutedEventArgs e)
        {
           family1.
        }

        private void btnsearch_Click(object sender,RoutedEventArgs e)
        {
            family1.searchtext = this.txtsearch.Text.Trim();
            family1.searchmembercommand.Execute(null );
        }
    }
运行一下看看,点击添加删除,是不是提示成功了。别以为到这里就真的会了mvvm,仔细想想,是不是有一点感觉:绕老绕去的写了好多代码其实都是在做无用功,特别是那个Icommand接口。如果你这么想,就说明你真的用心学了。
11.真谛:如果mvvm是象上面那样写程序,那还不如不要呢!记得前面我们白话的时候提过,view就像美女一样,基本靠“绑”,所以删除我们的哪些语句,让click事件滚蛋,直接在view的xaml文件中把命令绑上去。代码如下:
            <Button Name="btnsearch" Content="查询" Command="{Binding searchmembercommand}"/>
            <Button Name="btnadd" Content="添加" Command="{Binding addfamilymembercommand}" />
            <Button Name="btndel" Content="删除" Command="{Binding deletefamilymembercommand}" />
12.再次运行,看看是不是一样的效果。现在你应该明白这种模式的优势了吧,界面设计和程序设计者之间的自由度是不是发挥到了极致。

不过程序到这里其实还没有完.....

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐