Prism4示例学习二_PrismMVVMP(原创).doc_第1页
Prism4示例学习二_PrismMVVMP(原创).doc_第2页
Prism4示例学习二_PrismMVVMP(原创).doc_第3页
Prism4示例学习二_PrismMVVMP(原创).doc_第4页
Prism4示例学习二_PrismMVVMP(原创).doc_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

PrismMVVMP示例下载地址:/开发包:Silverlight 4.0,Prism 4.0开发平台:Visual Studio 2010PrismMVVMPNoPrismMVVMPSample这个解决方案没有使用Prism框架,它要实现的功能很简单,点击按钮,显示“Hello World”。程序入口点在App.xaml.cs中。App.xaml.csusing System.Windows;using Microsoft.Practices.Unity;namespace NoPrismMVVMPSample public partial class App : Application protected override void OnStartup(StartupEventArgs e) base.OnStartup(e); IUnityContainer container = new UnityContainer(); RegisterTypes(container); var view = container.Resolve().View; view.Show(); static void RegisterTypes(IUnityContainer container) container.RegisterType(); App.xaml.cs虽然简单,我们还是解释一下。OnStartup方法是系统自带的,继承自System.Windows.Application类。系统使用了Dependency Injection Container,完成MainWindow的注册,和MainWindowPresenter的加载。然后系统就进入MVVMP的运行轨道了。MainWindowPresenter.csnamespace NoPrismMVVMPSample class MainWindowPresenter MainWindowViewModel viewModel; public IMainWindow View get; private set; public MainWindowPresenter(IMainWindow view) this.View = view; this.viewModel = new MainWindowViewModel(); this.viewModel.KeepAlive = this; this.viewModel.ClickCommand = new DelegateCommand(ClickCommand_Execute, _=true); View.DataContext = viewModel; void ClickCommand_Execute(object args) viewModel.Message = Hello, World; Presenter整合View和ViewModel,同时处理ClickCommand命令。Presenter大包大揽,忙前忙后。ViewModel只要处理好提供给View的那两个Binding属性,ClickCommand和Message就没事了。View更简单,Binding好ClickCommand和Message就OK了。在这里值得一提的是INotifyPropertyChanged接口的使用。MainWindowViewModel.csusing System.ComponentModel;using System.Windows.Input;namespace NoPrismMVVMPSample class MainWindowViewModel: INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged = delegate ; public object KeepAlive get; set; public ICommand ClickCommand get; set; string message; public string Message get return message; set message = value; PropertyChanged(this, new PropertyChangedEventArgs(Message); MainWindowViewModel类实现INotifyPropertyChanged接口,这个接口只有一个事件需要且必须实现,那就是PropertyChanged事件。当你在Presenter中更改ViewModel的Message属性值时,例如:viewModel.Message = Hello, World。ViewModel中Message的setter方法执行,PropertyChanged事件被触发,通知与Message有绑定关系的属性更新内容。INotifyPropertyChanged接口很有用。因为你可以看到,上面的ViewModel代码里根本没有针对View页面的引用。反之,View页面中(包括后置代码)也没有ViewModel的任何调用。说白了,View和ViewModel在编译阶段是彼此隔离的,谁也不知道谁的存在。那么怎样建立起二者的联系,让ViewModel中的Message属性发生改变,View中内容也相应变化呢?全靠INotifyPropertyChanged接口了。PrismMVVMPPrismMVVMPSample这是一个引入Prism框架的解决方案,它实现了计算器的基本功能。我们要关注的内容是: Bootstrapper 类间关系 Lambda表达式 泛型 类的抽象与继承 Event Aggregation NotificationObjectBootstrapper.csusing System.Windows;using Microsoft.Practices.Prism.Modularity;using Microsoft.Practices.Prism.UnityExtensions;using Microsoft.Practices.Unity;namespace PrismMVVMPSample class Bootstrapper: UnityBootstrapper protected override DependencyObject CreateShell() var shell = Container.Resolve(); shell.Show(); return shell; protected override IModuleCatalog CreateModuleCatalog() var catalog = new ModuleCatalog(); catalog.AddModule(typeof(LEDModule.LEDModule); catalog.AddModule(typeof(KeypadModule.KeypadModule); return catalog; 两个override方法,先执行CreateModuleCatalog,加载LEDModule和KeypadModule,然后执行CreateShell,创建shell。注意,创建shell结束后,系统才会真正创建LEDModule和KeypadModule。类LEDModule就是我们分析PrismMVVMPSample.LEDModule的入口点,LEDModule继承自类ModuleBase,而类ModuleBase又实现了IModule接口。静态类结构图如下:ModuleBase.csusing Microsoft.Practices.Prism.Modularity;using Microsoft.Practices.Prism.Regions;using Microsoft.Practices.Unity;namespace PrismMVVMPSample.Infrastructure public class ModuleBase: IModule protected IUnityContainer Container get; private set; protected IRegionViewRegistry RegionRegistry get; private set; public ModuleBase(IUnityContainer container, IRegionViewRegistry regionRegistry) this.Container = container; this.RegionRegistry = regionRegistry; public void Initialize() ConfigureContainer(); InitializeModule(); protected virtual void ConfigureContainer() protected virtual void InitializeModule() 故事是这样的,某小弟LEDModule出事了,做大哥的ModuleBase自然要出马,于是ModuleBase利用与IModule的关系,为小弟LEDModule提供了如下资源: Container RegionRegistry 两个待实现的方法ConfigureContainer和InitializeModule,让小弟们自己去做 以及这两个方法的执行顺序(ModuleBase中的Initialize方法),这个要大哥把关同理,小弟KeypadModule出事了,大哥ModuleBase一样对待。LEDModule.csusing Microsoft.Practices.Prism.Regions;using Microsoft.Practices.Unity;using PrismMVVMPSample.Infrastructure;using PrismMVVMPSample.LEDModule.LED;namespace PrismMVVMPSample.LEDModule public class LEDModule: ModuleBase public LEDModule(IUnityContainer container, IRegionViewRegistry regionRegistry) : base(container, regionRegistry) protected override void ConfigureContainer() base.ConfigureContainer(); Container.RegisterType(); Container.RegisterTypeIPresenter, LEDPresenter(); protected override void InitializeModule() base.InitializeModule(); RegionRegistry.RegisterViewWithRegion(RegionNames.LEDRegion, () = Container.ResolveIPresenter().View); 那么小弟LEDModule是怎么执行大哥吩咐的事呢?ConfigureContainer方法中的RegisterType就不多解释了,DI(Dependency Injection)的惯用手法。InitializeModule方法中的RegisterViewWithRegion我们要讲一讲。IRegionViewRegistry来自Microsoft.Practices.Prism.Regions,定义了RegisterViewWithRegion方法。这个方法把某个类返回的内容注册到某个Region上。() = Container.Resolve IPresenter().View,这是个什么东西?这句话是Lambda表达式,=是参数赋值运算符,表示把=左边的参数(如果有)赋值给=右边的语句块或表达式。() = xxxxxx中的空括号表示右边没有参数,但是括号是必须要的。这样你就明白了,这句话就是调用Container.Resolve方法返回一个View页面。OK,我们讨论到这里,基本把Module外围的执行功能和准备资源都解释清楚了,接下来就是进入每个Module内部了。题外话:我很钦佩写这个解决方案示例代码的程序员,他是一名出色的程序员。为什么这么说?因为他把接口、类、继承、实现等运用的非常好。代码谁都会写,类间的功能调用也不难做到。难就难在,如何有效的组织类,厘清类间的关系,耦合与解耦和。简而言之,如何洞悉事物的本质。我们以LEDModule为例,分析一下Module内部的情况。LEDModule就是典型的MVVMP Pattern。类结构图如下:LEDPresenter.csusing Microsoft.Practices.Prism.Events;using PrismMVVMPSample.Infrastructure;using PrismMVVMPSample.Infrastructure.Model;namespace PrismMVVMPSample.LEDModule.LED class LEDPresenter: PresenterBase public LEDPresenter(ILEDView view, IEventAggregator eventAggregator): base(view) eventAggregator.GetEvent().Subscribe(OnResultChanged); void OnResultChanged(int result) ViewModel.Result = result; LEDPresenter继承自PresenterBase,构造函数中就一句话,eventAggregator.GetEvent().Subscribe(OnResultChanged);声明了Event Aggregation的Subscriber的事件接收处理方法OnResultChanged。而事件的发送者在KeypadModule中的类KeypadPresenter里。void UpdateResult(int result)eventAggregator.GetEvent().Publish(result);注:如果你不了解Event Aggregation,请参考我的另一篇文章Prism4TrainingKit学习心得。LEDPresenter代码可真够简单的啊。那么围绕在它周围的View、ViewModel们怎么样呢?View页面就放了个Label控件,Binding了个Result数据源,View页面的后置代码里啥也没做。ViewModel里就是声明了个Result属性,用来提供数据Binding。LEDPresenter、LEDView、LEDViewModel都写得这么简单,好多该做的事都没有做啊。对,是有很多事在LED包里没有做,不过不等于真的没做。LED包外还有个上流社会,它们在制定规则,建立关系,决定着事情的发展。这个上流社会就是PrismMVVMPSample.Infrastructure项目这个上流社会其实也是个MVVMP Pattern,这个模式的核心是PresenterBase.cs。整个模式就是把一般的MVVMP Pattern中通用的语句、逻辑和类间关系抽象出来,形成一个通用的结构并重复使用。下面我们逐一介绍一下这些大哥级的人物。第一个出场的就是类ModuleBase,它是所有Module的大哥,本文的前面也已经详细的说明了。下一个出场的是类ViewModelBaseViewModelBase.csusing Microsoft.Practices.Prism.ViewModel;namespace PrismMVVMPSample.Infrastructure public class ViewModelBase: NotificationObject public object KeepAlive get; set; 类ViewModelBase只定义了一个属性KeepAlive,不过它继承自NotificationObject。NotificationObject是做什么的呢?还记得本文开始部分列举的那个NoPrismMVVMPSample示例吗?那个示例里有个MainWindowViewModel,实现了INotifyPropertyChanged接口。NotificationObject就是专门实现INotifyPropertyChanged接口的。这意味着什么呢?故事是这样的,大哥ViewModelBase发话了,以后凡是出自我门下的ViewModel,一律采用NotificationObject实现INotifyPropertyChanged接口的方式,来处理属性更改事件。接下来登场的是IView和IPresenter两个接口namespace PrismMVVMPSample.Infrastructure public interface IView object DataContext get; set; namespace PrismMVVMPSample.Infrastructure public interface IPresenter where TView:IView TView View get; 这两位基本算是

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论