博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【学习笔记】Silverlight框架:Jounce(6)——Command和ViewModel
阅读量:5275 次
发布时间:2019-06-14

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

MVVM支持可以说是每个框架的标配了。

Jounce的这个部分也是参考了其他的几个框架,这里面东西比较多:

ActionCommand基本上就是Prism里的DelegateCommand,不过只有个泛型的版本。

BaseNotify则类似Prism里的NotificationObject,里面多了个方法,比较新奇:

ContractedBlock.gif
ExpandedBlockStart.gif
RaisePropertyChanged
1         ///   2         ///     Raise a property change and infer the frame from the stack  3         ///   4         /// 
5 /// May not work on some systems (64-bit, for example, not yet supported by Silverlight). 6 ///
7 [MethodImpl(MethodImplOptions.NoInlining)] 8 public virtual void RaisePropertyChanged() 9 {
10 var frames = new System.Diagnostics.StackTrace(); 11 for (var i = 0; i < frames.FrameCount; i++) 12 {
13 var frame = frames.GetFrame(i).GetMethod() as MethodInfo; 14 if (frame != null) 15 if (frame.IsSpecialName && frame.Name.StartsWith("set_")) 16 {
17 RaisePropertyChanged(frame.Name.Substring(4)); 18 return; 19 } 20 } 21 throw new InvalidOperationException("NotifyPropertyChanged() can only by invoked within a property setter."); 22 }

可见这个方法只能在set里用,而且并不是任何环境下都能用的,别的框架里只有在MVVM Light中看到过。

BaseViewModel继承自BaseNotify并实现了IViewModel接口,IViewModel里定义了用于初始化、导航和控制VisualState的方法,是绑定ViewModel和View的基础,从代码上来看,如果要通过Jounce框架进行绑定的话,ViewModel需继承自BaseViewModel。

BaseEntityViewModel继承自BaseViewModel并实现了INotifyDataErrorInfo接口,提供用于验证的基本方法和一个CommitCommand用于提交。

在Jounce中对于ViewModel需添加ExportAsViewModelAttribute,View需添加ExportAsViewAttribute,两者的关联则通过ViewModelRoute进行。

还是看代码来的实在,新建个解决方案,结构如下:

EntityViewModel继承自BaseEntityViewModel,对应的View是EntityView,用于演示如何使用Validate和Committe,代码如下:

ContractedBlock.gif
ExpandedBlockStart.gif
EntityViewModel.cs
1     [ExportAsViewModel("EntityViewModel")]  2     public class EntityViewModel : BaseEntityViewModel  3     {
4 private string _name; 5 private string _age; 6 7 public string Name 8 {
9 get { return _name; } 10 set 11 {
12 _name = value; 13 this.RaisePropertyChanged(); 14 this.ValidateName(); 15 } 16 } 17 18 public string Age 19 {
20 get { return _age; } 21 set 22 {
23 _age = value; 24 this.RaisePropertyChanged(); 25 this.ValidateAge(); 26 } 27 } 28 29 private void ValidateName() 30 {
31 this.ClearErrors(() => this.Name); 32 if (string.IsNullOrWhiteSpace(this.Name)) 33 {
34 this.SetError(() => this.Name, "请输入姓名!"); 35 } 36 } 37 38 private void ValidateAge() 39 {
40 this.ClearErrors(() => this.Age); 41 if (string.IsNullOrWhiteSpace(this.Age)) 42 {
43 this.SetError(() => this.Age, "请输入年龄!"); 44 } 45 else if (!Regex.IsMatch(this.Age, "^[0-9]*$")) 46 {
47 this.SetError(() => this.Age, "年龄需为数字!"); 48 } 49 } 50 51 protected override void ValidateAll() 52 {
53 this.ValidateName(); 54 this.ValidateAge(); 55 } 56 57 protected override void OnCommitted() 58 {
59 MessageBox.Show(string.Format("姓名:{0}\r\n年龄:{1}", this.Name, this.Age)); 60 61 this.Name = string.Empty; 62 this.ClearErrors(() => this.Name); 63 64 this.Age = string.Empty; 65 this.ClearErrors(() => this.Age); 66 } 67 }

EntityViewModel定义了2个简单的属性和验证方法,并重写了基类的ValidateAll和OnCommitted方法,当CommitCommand被调用时,会先调用ValidateAll,如果验证通过则会调用OnCommitted。

ContractedBlock.gif
ExpandedBlockStart.gif
EntityView.xaml
1 
8 9
10
11
12
13
14
15
16
17
18
19
20
22 23
24
26 27
28
29

Xaml里无非是一些绑定。

ContractedBlock.gif
ExpandedBlockStart.gif
EntityView.xaml.cs
1     public partial class EntityView : UserControl 2     {
3 public EntityView() 4 {
5 InitializeComponent(); 6 } 7 }

需要注意的是,这里我们并没有为EntityView添加ExportAsViewAttribute,这个页面会被嵌套在MainPage里,并在那里进行导出。

ContractedBlock.gif
ExpandedBlockStart.gif
MainPage.xaml
1 
9 10
11
12
13
14
17
18
19
20 21
22
23
24
25
26

给嵌入的EntityView定义Name,并在后台代码中定义导出视图:

ContractedBlock.gif
ExpandedBlockStart.gif
MainPage.xaml.cs
1     [ExportAsView(typeof(MainPage), IsShell = true)]  2     public partial class MainPage : UserControl  3     {
4 public MainPage() 5 {
6 InitializeComponent(); 7 } 8 9 [ExportAsView("EntityView")] 10 public UserControl ExportEntityView 11 {
12 get { return this.EntityView; } 13 } 14 }

MainViewModel是直接继承自BaseViewModel,自定义了一个简单的Command并重写了ActivateView方法。

ContractedBlock.gif
ExpandedBlockStart.gif
MainViewModel.cs
1     [ExportAsViewModel(typeof(MainViewModel))]  2     public class MainViewModel : BaseViewModel  3     {
4 public DateTime Time { get; private set; } 5 6 public ICommand RefreshTimeCommand { get; private set; } 7 8 public MainViewModel() 9 {
10 this.RefreshTimeCommand = new ActionCommand( 11 p => 12 {
13 this.Time = DateTime.Now; 14 this.RaisePropertyChanged(() => Time); 15 }); 16 this.RefreshTimeCommand.Execute(null); 17 } 18 19 protected override void ActivateView(string viewName, IDictionary
viewParameters) 20 {
21 this.EventAggregator.Publish("EntityView".AsViewNavigationArgs()); 22 } 23 }

最后还有Bindings用于指定ViewModel和View的关联。

ContractedBlock.gif
ExpandedBlockStart.gif
Bindings.cs
1     public class Bindings  2     {
3 [Export] 4 public ViewModelRoute MainBinding 5 {
6 get 7 {
8 return ViewModelRoute.Create
(); 9 } 10 } 11 12 [Export] 13 public ViewModelRoute EntityBinding 14 {
15 get 16 {
17 return ViewModelRoute.Create("EntityViewModel", "EntityView"); 18 } 19 } 20 }

可以看到的是ViewModelRoute、ExportAsViewModelAttribute和ExportAsViewAttribute都提供了不同的重载方法。

ExportAsViewModelAttribute和ExportAsViewAttribute都是继承自ExportAttribute,所以会被MEF导出。

框架的粗略流程是这样的:先找到设置了IsShell = true的View,这里就是MainPage,通过事件机制激活,绑定到关联的MainViewModel,调用MainViewModel的ActivateView方法,再通过事件机制激活EntityView,绑定到关联的EntityViewModel。更具体的内部流程下次再记。

转载于:https://www.cnblogs.com/HalfwayMonk/archive/2011/08/04/2126709.html

你可能感兴趣的文章
分布式计算开源框架Hadoop介绍
查看>>
安卓平台接口剖析
查看>>
坏的事情不都会带来坏的结果
查看>>
RPC的基础:调研EOS插件http_plugin
查看>>
第二次团队冲刺第二天
查看>>
bzoj 2257 (JSOI 2009) 瓶子与燃料
查看>>
11)Java abstract class 和 interface
查看>>
使用xrdp或Xmanager 远程连接 CentOS6
查看>>
Linux误删恢复
查看>>
Unity调用Windows窗口句柄,选择文件和目录
查看>>
HashMap循环遍历方式
查看>>
React Native 入门 调试项目
查看>>
C# 通过 Quartz .NET 实现 schedule job 的处理
查看>>
关于java之socket输入流输出流可否放在不同的线程里进行处理
查看>>
目前为止用过的最好的Json互转工具类ConvertJson
查看>>
Day13
查看>>
tensorflow saver简介+Demo with linear-model
查看>>
Luogu_4103 [HEOI2014]大工程
查看>>
Oracle——SQL基础
查看>>
项目置顶随笔
查看>>