`

[Silverlight入门系列]使用MVVM模式(7):ViewModel的INotifyPropertyChanged接口实现

    博客分类:
  • MVVM
阅读更多

上一篇说到《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
分享到:
评论
1 楼 Lstoryc 2014-01-28  
能分享一下源码么? 谢谢

相关推荐

    [SilverLight 入门知识]INotifyPropertyChanged 接口

    3. MVVM 模式:在 SilverLight 中,MVVM(Model-View-ViewModel)模式广泛使用,INotifyPropertyChanged 是实现 ViewModel 与 View 之间数据交互的关键。 4. 优化性能:通过 INotifyPropertyChanged,只在真正需要...

    实现mvvm模式 Silverlight

    MVVM(Model-View-ViewModel)模式是一种设计模式,尤其在开发富客户端应用程序时非常流行,如Silverlight。这种模式将应用程序分为三个主要组件:模型(Model)、视图(View)和视图模型(ViewModel)。MVVM的核心...

    silverlight MVVM模式示例

    在Silverlight中,ViewModel通常会实现INotifyPropertyChanged接口,以便在属性更改时通知视图更新。此外,它还可能实现ICommand接口,提供命令功能,使视图能够响应用户的操作。 **4. 数据绑定** 在Silverlight中...

    INotifyPropertyChanged接口在Silverlight中使用的例子

    INotifyPropertyChanged接口是.NET框架中一个非常重要的设计模式,它主要用于实现数据绑定的实时更新。在Silverlight中,这个接口的应用尤为关键,因为Silverlight的数据绑定机制依赖于它来感知对象属性的变化并自动...

    使用Command机制实现的Silverlight4.0多层MVVM模式简单案例

    在Silverlight 4.0中,可以使用`INotifyPropertyChanged`接口来实现属性改变的通知,而`ICommand`接口则用于实现命令。 **4. Command(命令)** 在Silverlight 4.0中,`ICommand`接口允许我们创建可执行的操作,...

    Silverlight中使用MVVM

    ViewModel实现了INotifyPropertyChanged接口,用于通知视图数据的改变。此外,ViewModel还包含了一些命令(Command),这些命令封装了视图的操作逻辑,使得视图可以响应用户的操作,同时保持视图的无状态。 **4. ...

    Silverlight中使用MVVM.docx

    在Silverlight应用中,MVVM(Model-View-ViewModel)是一种设计模式,它提倡将业务逻辑、用户界面和数据模型分离,从而实现更清晰的代码结构和更好的可测试性。以下是对MVVM模式在Silverlight中的应用进行的详细说明...

    关于silverlight中MVVM模式下的数据验证

    在Silverlight应用开发中,MVVM(Model-View-ViewModel)模式是一种常用的设计模式,它将业务逻辑、用户界面和数据模型分离,提高了代码的可测试性和可维护性。本篇将深入探讨在Silverlight中如何在MVVM模式下进行...

    MVVM模式示例

    MVVM(Model-View-ViewModel)是一种设计模式,广泛应用于微软的XAML平台,如WPF(Windows Presentation Foundation)、Silverlight以及Windows Phone 7等。该模式旨在提高应用的可测试性,同时促进开发人员与设计...

    silverlight mvvm 增删改差

    ViewModel是MVVM的核心,它实现了INotifyPropertyChanged接口,以便在属性改变时通知View进行更新。此外,ViewModel还定义了一些Command,用于触发增删改查操作。这些Command遵循命令设计模式,使得View可以无须关心...

    MVVM(Model-View-ViewModel)实例讲解

    MVVM(Model-View-ViewModel)是一种设计模式,主要用于构建用户界面,特别是在WPF(Windows Presentation Foundation)和Silverlight应用程序中。它源自于MVC(Model-View-Controller)模式,但针对UI开发进行了...

    基于MVVM的silverlight程序

    而MVVM(Model-View-ViewModel)模式则是一种流行的设计模式,尤其在WPF和Silverlight等UI框架中广泛应用。本文将深入探讨如何在Silverlight项目中应用MVVM模式,以创建高效、可维护的程序。 **MVVM模式** MVVM...

    silverlight mvvm demo

    通过分析“silverlight mvvm demo”,我们可以学习到如何在实践中应用MVVM模式,包括如何创建ViewModel、如何进行数据绑定、如何定义和使用命令等。同时,这也有助于我们更好地理解和掌握Silverlight的开发技巧,...

    Apress.-.Pro.WPF.and.Silverlight.MVVM.2010

    本书深入探讨了WPF(Windows Presentation Foundation)和Silverlight框架下的MVVM(Model-View-ViewModel)设计模式的应用,为软件开发者提供了构建高质量、可维护性高和可测试性强的用户界面应用程序的方法。...

    Silverlight-MVVM简单示例

    ViewModel通常是普通的C#类,它包含了视图所需的数据属性和命令,这些属性通常使用`INotifyPropertyChanged`接口来实现自动数据绑定更新。 **MVVM在Silverlight中的应用** 在"Silverlight-MVVM简单示例"项目中,...

    Silverlight MVVM

    ViewModel还应实现INotifyPropertyChanged接口,以便在属性更改时通知视图更新。 4. **数据绑定(Data Binding)** 数据绑定是Silverlight MVVM模式的核心特性,它允许视图自动显示和更新视图模型的属性值。双向...

    MIX10-MVVM-Samples

    MVVM-Samples" 是一个专为开发者设计的压缩包,它包含了多个示例项目,展示了如何在WPF(Windows Presentation Foundation)、Silverlight以及Windows Phone 7平台上应用MVVM(Model-View-ViewModel)设计模式。...

    使用 Model-View-ViewModel 的问题和详细介绍说明

    Model-View-ViewModel (MVVM) 是一种设计模式,尤其适用于Windows Presentation Foundation (WPF) 和 Silverlight 应用程序的开发。它旨在提高代码的可维护性和可测试性,通过将视图(View)、模型(Model)和视图...

    MvvmLight 简单demo

    1. **GalaSoft.MvvmLight Library**:这是MvvmLight的核心库,包含了各种帮助类和接口,如 GalaSoft.MvvmLight.ViewModelBase,它是ViewModel的基础类,提供了INotifyPropertyChanged和ICommand的实现。 2. **...

    MVVMLight.zip

    这个框架提供了一系列工具和库,帮助开发者遵循MVVM设计模式,实现更加模块化、可测试且易于维护的代码。 **1. MVVM模式介绍** MVVM模式是一种软件设计模式,它将用户界面(View)与业务逻辑(ViewModel)分离,...

Global site tag (gtag.js) - Google Analytics