上一篇说到《Model的INotifyPropertyChanged接口实现》和在Prism中有《NotificationObject自动实现INotifyPropertyChanged接口》,很好,本文说说ViewModel的这个INotifyPropertyChanged接口可以用来做啥?
举例1:我有个TabControl,里面放了很多View,每个由ViewModel控制,我想是想TabSelectionChanged就打开相应的ViewModel,怎么做?
解答:用ViewModel的INotifyPropertyChanged接口实现,因为TabItem作为一个选择器就有 IsSelected属性,把这个属性绑定到ViewModel的IsSelected字段,然后这个字段改变的时候用INotifyPropertyChanged接口实现通知即可。整个流程用MVVM实现非常整洁。
Xaml
1 <TabControl ...> 2 <TabControl.ItemContainerStyle> 3 <Style TargetType="{x:Type TabItem}"> 4 <Setter Property="IsSelected" 5 Value="{Binding Path=IsSelected,Mode=TwoWay}"/> 6 </Style> 7 </TabControl.ItemContainerStyle> 8 </TabControl>
ViewModel
1 public class MyViewModel : INotifyPropertyChanged 2 { 3 private bool _isLoaded; 4 5 private void Load() 6 { 7 // code 8 } 9 10 private bool _isSelected; 11 12 public bool IsSelected 13 { 14 get 15 { 16 return this._isSelected; 17 } 18 set 19 { 20 if (this._isSelected != value) 21 { 22 this._isSelected = value; 23 24 if (this._isSelected && !this._isLoaded) 25 { 26 this.Load(); 27 this._isLoaded = true; 28 } 29 30 var propertyChanged = this.PropertyChanged; 31 if (propertyChanged != null) 32 { 33 propertyChanged(this, new PropertyChangedEventArgs("IsSelected")); 34 } 35 } 36 } 37 } 38 39 public event PropertyChangedEventHandler PropertyChanged; 40 }
举例2:我有个TreeView,里面的项非常复杂,还需要惰性加载(点击了才取数据并展开),怎么用MVVM实现?彻底晕了
解答:还是用ViewModel的INotifyPropertyChanged接口实现,要使得你的视图没有代码,就要你不再把TreeView当成一个存储数据的地方,而是看做一个展现数据的地方,那么一切都将水到渠成。这就是ViewModel这个想法的由来。而用INotifyPropertyChanged接口可以神奇的实现它们之间的解耦。
Xaml
1 <TreeView ItemsSource="{Binding FirstGeneration}"> 2 <TreeView.ItemContainerStyle> 3 <!-- 4 This Style binds a TreeViewItem to a PersonViewModel. 5 --> 6 <Style TargetType="{x:Type TreeViewItem}"> 7 <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> 8 <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 9 <Setter Property="FontWeight" Value="Normal" /> 10 <Style.Triggers> 11 <Trigger Property="IsSelected" Value="True"> 12 <Setter Property="FontWeight" Value="Bold" /> 13 </Trigger> 14 </Style.Triggers> 15 </Style> 16 </TreeView.ItemContainerStyle> 17 18 <TreeView.ItemTemplate> 19 <HierarchicalDataTemplate ItemsSource="{Binding Children}"> 20 <TextBlock Text="{Binding Name}" /> 21 </HierarchicalDataTemplate> 22 </TreeView.ItemTemplate> 23 </TreeView>
ViewModel
1 public class PersonViewModel 2 { 3 public PersonViewModel(Person person) 4 : this(person, null) 5 { 6 } 7 8 private PersonViewModel(Person person, PersonViewModel parent) 9 { 10 _person = person; 11 _parent = parent; 12 13 _children = new ReadOnlyCollection<PersonViewModel>( 14 (from child in _person.Children 15 select new PersonViewModel(child, this)) 16 .ToList<PersonViewModel>()); 17 } 18 19 private bool _isSelected; 20 public bool IsSelected 21 { 22 get { return _isSelected; } 23 set 24 { 25 if (value != _isSelected) 26 { 27 _isSelected = value; 28 this.OnPropertyChanged("IsSelected"); 29 } 30 } 31 } 32 33 private bool _isExpanded; 34 public bool IsExpanded 35 { 36 get { return _isExpanded; } 37 set 38 { 39 if (value != _isExpanded) 40 { 41 _isExpanded = value; 42 this.OnPropertyChanged("IsExpanded"); 43 } 44 45 // Expand all the way up to the root. 46 if (_isExpanded && _parent != null) 47 _parent.IsExpanded = true; 48 } 49 } 50 public string Name 51 { 52 get { return _person.Name; } 53 } 54 } 55 public class Person 56 { 57 readonly List<Person> _children = new List<Person>(); 58 public IList<Person> Children 59 { 60 get { return _children; } 61 } 62 63 public string Name { get; set; } 64 }
按需加载:
View Code
1 interface ITreeViewItemViewModel : INotifyPropertyChanged 2 { 3 ObservableCollection<TreeViewItemViewModel> Children { get; } 4 bool HasDummyChild { get; } 5 bool IsExpanded { get; set; } 6 bool IsSelected { get; set; } 7 TreeViewItemViewModel Parent { get; } 8 } 9 public TreeViewItemViewModel : ITreeViewItemViewModel 10 { 11 protected TreeViewItemViewModel(TreeViewItemViewModel parent, bool lazyLoadChildren) 12 { 13 _parent = parent; 14 15 _children = new ObservableCollection<TreeViewItemViewModel>(); 16 17 if (lazyLoadChildren) 18 _children.Add(DummyChild); 19 } 20 public bool IsExpanded 21 { 22 get { return _isExpanded; } 23 set 24 { 25 if (value != _isExpanded) 26 { 27 _isExpanded = value; 28 this.OnPropertyChanged("IsExpanded"); 29 } 30 31 // Expand all the way up to the root. 32 if (_isExpanded && _parent != null) 33 _parent.IsExpanded = true; 34 35 // Lazy load the child items, if necessary. 36 if (this.HasDummyChild) 37 { 38 this.Children.Remove(DummyChild); 39 this.LoadChildren(); 40 } 41 } 42 } 43 44 /// <summary> 45 /// Returns true if this object's Children have not yet been populated. 46 /// </summary> 47 public bool HasDummyChild 48 { 49 get { return this.Children.Count == 1 && this.Children[0] == DummyChild; } 50 } 51 52 /// <summary> 53 /// Invoked when the child items need to be loaded on demand. 54 /// Subclasses can override this to populate the Children collection. 55 /// </summary> 56 protected virtual void LoadChildren() 57 { 58 } 59 }
真正加载子项的工作留给子类去实现。它们重载LoadChildren方法来提供一个跟类型相关的加载子项的实现。比如下面的RegionViewModel类,它重载了该方法来加载State对象并且创建StateViewModel对象。
View Code
1 public class RegionViewModel : TreeViewItemViewModel 2 { 3 readonly Region _region; 4 5 public RegionViewModel(Region region) 6 : base(null, true) 7 { 8 _region = region; 9 } 10 11 public string RegionName 12 { 13 get { return _region.RegionName; } 14 } 15 16 protected override void LoadChildren() 17 { 18 foreach (State state in Database.GetStates(_region)) 19 base.Children.Add(new StateViewModel(state, this)); 20 } 21 }
Xaml
1 <TreeView ItemsSource="{Binding Regions}"> 2 <TreeView.ItemContainerStyle> 3 <!-- 4 This Style binds a TreeViewItem to a TreeViewItemViewModel. 5 --> 6 <Style TargetType="{x:Type TreeViewItem}"> 7 <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> 8 <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 9 <Setter Property="FontWeight" Value="Normal" /> 10 <Style.Triggers> 11 <Trigger Property="IsSelected" Value="True"> 12 <Setter Property="FontWeight" Value="Bold" /> 13 </Trigger> 14 </Style.Triggers> 15 </Style> 16 </TreeView.ItemContainerStyle> 17 18 <TreeView.Resources> 19 <HierarchicalDataTemplate 20 DataType="{x:Type local:RegionViewModel}color: #0000f发表评论
-
[Silverlight入门系列]使用MVVM模式(6):使用Behavior
2011-06-06 20:42 1592Behavior把一些常用的行为封装成可重复使用的组件(C ... -
[Silverlight入门系列]使用MVVM模式(5):异步Validation数据验证和INotifyDataErrorInfo接口
2011-06-06 20:40 1125数据验证(Validation)是界面程序的常见需求,例如 ... -
[Silverlight入门系列]使用MVVM模式(4):Prism的NotificationObject自动实现INotifyPropertyChanged接
2011-06-06 20:37 1369在上一篇写了Model的INotifyPropertyChan ... -
[Silverlight入门系列]使用MVVM模式(3):Model的INotifyPropertyChanged接口实现
2011-06-06 20:36 961当客户端绑定一个数据模型以后,数据模型变化以后可以自动通知 ... -
[Silverlight入门系列]使用MVVM模式(2):集合
2011-06-06 20:33 1152Model /ObservableCollection/ICo ... -
[Silverlight入门系列]使用MVVM模式(1):MVVM核心概念
2011-06-06 20:26 1590MVVM模式是Model、View、ViewModel的简称, ...
相关推荐
Silverlight中MVVM(Model_ViewModel_View)设计模式的经典实例 Silverlight无数设计师最钟爱的设计模式 Silverlight设计的王者模式 Silverlight设计的首选模式
Mvvm: ViewModel+LiveData+DataBinding+Retrofit+Room实践
如何创建更好的Silverlight程序系列课程(3):Silverlight & MVVM
"MVVM in Delphi: Architecting and Building Model View ViewModel Applications" 2016 | ISBN-10: 148422213X | 143 pages | PDF, EPUB | 23 MB Dive into the world of MVVM, learn how to build modern ...
MVVM模式(模型视图ViewModel) 演示版 建筑学 流 屏幕截图 滑梯 Android MVVM https://docs.google.com/presentation/d/1nTwtU8OWYs_8Q3i_3hOPAWodDpDKzO--uA-4b6LUr8g/edit?usp=sharing Android MVVM Clean ...
结合WPF、Silverlight绑定机制,MVP演变出了MVVM,充分利用了WPF、Silverlight的优势,将大量代码逻辑、状态转到ViewModel, 可以说MVVM是专门为WPF、Silverlight打造的。 View绑定到ViewModel,然后执行一些命令在...
快速开发框架java+mvvm+retrofit+viewmodel+livedata
Wpf Mvvm模式下窗口ShowDialog的实现
主要对mvvm框架的设计ICommand和INotifyPropertyChanged接口的使用
Silverlight MVVM模式Silverlight MVVM模式Silverlight MVVM模式
关键代码:实现接口INotifyPropertyChanged 2)ViewModel:定义算法操作数据结构(数据集合,增加,删除,修改,查询) 关键代码:继承ViewModelBase 定义一个集合ObservableCollection<c401xmmc> C401xmmcs 3)...
但是最重要的问题是怎么在MVVM架构中去实现模式窗口,即怎么在ViewMode中实现,同时要实现View层和ViewModel的松耦性,另外依照MVVM架构思想,ViewModel层不必知道View的样式,所以我们必须需要一个接口...
实现mvvm模式 Silverlight
Vue.js是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动...
silverlight 中mvvm 的使用详解
[Packt Publishing] 企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) (英文版) [Packt Publishing] MVVM Survival Guide for Enterprise Architectures in Silverlight and WPF (E-Book) ☆ 出版信息:☆ ...
该资源使用MVVM编程模式,页面与逻辑分离的情况下,我们改动其中任何一个部分都是比较清楚的。
MVVM模式实现图片分页显示 (1)数据使用WCF服务加载 (2)定制ListBox数据模板 (3)采用MVVM模式实现分页 注意:在运行前需要修改WCF服务Service1.svc方法GetAllPictureData中的图片文件夹路径,默认是C:\Users\My...
MVVM设计模式简单案例,本案例分为多层实现,适合初学者使用。