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

本文说说ViewModel的这个INotifyPropertyChanged接口可以用来做啥?

 

举例1:我有个TabControl,里面放了很多View,每个由ViewModel控制,我想是想TabSelectionChanged就打开相应的ViewModel,怎么做?

解答:用ViewModel的INotifyPropertyChanged接口实现,因为TabItem作为一个选择器就有 IsSelected属性,把这个属性绑定到ViewModel的IsSelected字段,然后这个字段改变的时候用INotifyPropertyChanged接口实现通知即可。整个流程用MVVM实现非常整洁。

ExpandedBlockStart.gifXaml
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>
ExpandedBlockStart.gifViewModel
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接口可以神奇的实现它们之间的解耦。

ExpandedBlockStart.gifXaml
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>

ExpandedBlockStart.gifViewModel
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 }

按需加载:

ExpandedBlockStart.gifView 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对象。

ExpandedBlockStart.gifView 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 }
ExpandedBlockStart.gifXaml
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}"
21 ItemsSource="{Binding Children}"
22 >
23 <StackPanel Orientation="Horizontal">
24 <Image Width="16" Height="16"
25 Margin="3,0" Source="Images"Region.png" />
26 <TextBlock Text="{Binding RegionName}" />
27 </StackPanel>
28 </HierarchicalDataTemplate>
29
30 <HierarchicalDataTemplate
31 DataType="{x:Type local:StateViewModel}"
32 ItemsSource="{Binding Children}"
33 >
34 <StackPanel Orientation="Horizontal">
35 <Image Width="16" Height="16"
36 Margin="3,0" Source="Images"State.png" />
37 <TextBlock Text="{Binding StateName}" />
38 </StackPanel>
39 </HierarchicalDataTemplate>
40
41 <DataTemplate DataType="{x:Type local:CityViewModel}">
42 <StackPanel Orientation="Horizontal">
43 <Image Width="16" Height="16"
44 Margin="3,0" Source="Images"City.png" />
45 <TextBlock Text="{Binding CityName}" />
46 </StackPanel>
47 </DataTemplate>
48 </TreeView.Resources>
49  </TreeView>

未完待续。

转载于:https://www.cnblogs.com/Areas/archive/2011/09/07/2169890.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361987.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[读书笔记]TCP/IP详解V1读书笔记-4 5

IP地址与以太网地址之间的关系 R P发送一份称作A R P请求的以太网数据帧给以太网上的每个主机。这个过程称作广播&#xff0c;在32 bit的I P地址和采用不同网络技术的硬件地址之间提供动态映射 ----------------------------------------- arp以太网帧的类型字段为x 0 8 0 6&am…

未来是Apache Karaf上的微服务架构

这是Jamie Goodyear的客座博客文章&#xff08; 博客 &#xff0c; icbts &#xff09;。 他是Savoir Technologies的开源倡导者&#xff0c;Apache开发人员和计算机系统分析师&#xff1b; 他为全球大型组织设计&#xff0c;批判和支持了体系结构。 他拥有纽芬兰纪念大学的计…

使用内存回流的方法来实现将image的内容转换为 byte[]

在今天的开发中老大不知道怎么突发奇想&#xff0c;要使用Image的Byte数据。当时使用老几种方式效果均不理想&#xff0c;最后发现其实可以使用内存回流的方式来实现。多的不说老&#xff0c;马上贴上代码&#xff1a;/**//// <summary> /// 将byte[]转换为Image…

通过设计国际象棋游戏来了解策略模式

今天&#xff0c;我们将借助一个示例来尝试了解策略模式。 我们将考虑的示例是国际象棋游戏。 这里的目的是解释策略模式&#xff0c;而不是构建全面的国际象棋游戏解决方案。 策略模式&#xff1a;策略模式被称为行为模式-用于管理对象之间的算法&#xff0c;关系和职责。 策…

群发邮件

最近&#xff0c;通过两周的学习&#xff0c;对.net 的基础知识有了进一步的了解。觉得自己可以写个小程序了。于是花了两天时间写了一个 群发邮件的一个WinForm小程序。自己在这里小秀一下&#xff0c;表扬及鼓励一下自己。哈哈&#xff01; 此小程序在发送邮件的基础上还添加…

Npm install failed with “cannot run in wd”

Linux环境下&#xff0c;root账户&#xff0c;安装某些npm包的时候报下面的错误&#xff0c;例如安装grunt-contrib-imagemin时&#xff1a; Error: EACCES, mkdir /usr/local/lib/node_modules/coffee-scriptnpm ERR! { [Error: EACCES, mkdir /usr/local/lib/node_modules/c…

我的Google Adsense帐户被关

一、 上周四&#xff0c;我收到Google的邮件&#xff0c;宣布关闭我的Adsense帐户。 "您好&#xff01; 查看了相关记录后&#xff0c;我们确认您的 AdSense 帐户存在引起无效活动的风险。保护 AdWords 广告客户&#xff0c;使其免受无效活动的侵害是我们的责任&#xff0…

csharp: ODP.NET,System.Data.OracleClient(.net 4.0) and System.Data.OleDb读取Oracle g 11.2.0的区别...

ODP.NET: 引用&#xff1a; using Oracle.DataAccess; //Oracle g 11.2.0 using Oracle.DataAccess.Client; using Oracle.DataAccess.Types; //下载 http://www.oracle.com/technetwork/topics/dotnet/downloads/net-downloads-160392.html //引用&#xff1a;D:\app\geovindu…

Java 9幕后花絮:新功能从何而来?

找出Java幕后发生的事情&#xff0c;以及新功能如何实现 在上一篇文章中&#xff0c;我们介绍了即将发布的Java 9版本的新功能和尚待解决的功能&#xff0c;并简要提到了将新功能添加到下一个版本之前要经历的过程。 由于此过程几乎影响了所有Java开发人员&#xff0c;但大多数…

sudo apt-get install libstdc++6

sudo apt-get install libstdc6 yum install libncurses.so.5 sudo apt-get install libncurses.so.5 sudo apt-get install lib32ncurses5 apt-get update把源更新一下 使用gdb时的指令 (gbd) info line *0x08xxxx sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.…

AngularJS快速入门指南03:表达式

AngularJS通过表达式将数据绑定到HTML。 AngularJS表达式 AngularJS表达式写在双大括号中&#xff1a;{{ 表达式语句 }}。 AngularJS表达式绑定数据到HTML的方式与ng-bind指令的方式相同。 AngularJS会准确地将表达式“输出”为计算的结果。 AngularJS表达式与JavaScript表达式…

零基础快速上手HarmonyOS ArkTS开发2---ArkTS开发实践

ArkTS开发实践&#xff1a; 接着上一次零基础快速上手HarmonyOS ArkTS开发1---运行Hello World、ArkTS开发语言介绍继续&#xff0c; 在上一次对于ArkTS的基础知识进行了学习&#xff0c;依照官方的课程计划&#xff0c;还有两个具体的小案例需要来实践实践&#xff1a; 实践出…

八、VueJs 填坑日记之参数传递及内容页面的开发

我们在上一篇博文中&#xff0c;渲染出来了一个列表&#xff0c;并在列表中使用了router-link标签&#xff0c;标签内的&#xff1a;to就是链接地址&#xff0c;昨天咱们是<router-link :to"/content/ i.id">这样写的&#xff0c;今天我们来完成内容页面的渲染…

为Kindeditor控件添加图片自动上传功能

Kindeditor是一款功能强大的开源在线HTML编辑器&#xff0c;支持所见即所得的编辑效果。它使用JavaScript编写&#xff0c;可以无缝地与多个不同的语言环境进行集成&#xff0c;如.NET、PHP、ASP、Java等。官方网站可以查看这里&#xff1a;http://kindeditor.net/index.php Ki…

4个万无一失的技巧让您开始使用JBoss BRMS 6.0.3

上周&#xff0c;红帽发布了标记为6.0.3的JBoss BRMS的下一版本&#xff0c;已订阅的用户可以在其客户门户中使用。 如果您对该版本的新增功能感到好奇&#xff0c;请在客户门户网站上在线查看版本说明和其余文档 。 我们正在寻找一些简单的方法来开始使用此新版本&#xff0…

带有Angular JS的Java EE 7 – CRUD,REST,验证–第2部分

这是Angular JS承诺的Java EE 7的后续版本–第1部分 。 花了比我预期更长的时间&#xff08;找到时间来准备代码和博客文章&#xff09;&#xff0c;但是终于到了&#xff01; 应用程序 第1部分中的原始应用程序只是带有分页的简单列表&#xff0c;以及提供列表数据的REST服务…

Chrome不显示OPTIONS请求的解决方法2021版chrome90

在chrome90上之前展示跨域请求预检请求的方法失效了&#xff1a; 在chrome地址栏总输入 chrome://flags/#out-of-blink-cors 将其设置为Disabled后重启浏览器 在chrome://flags找不到选项out-of-blink-cors。取而代之的是chrome将预检请求放到了控制台网络面板的 OTHER 面板中。…

SVG实现波浪效果

SVG实现波浪效果 svg path&#xff1a;C 贝塞尔曲线绘制波浪形状 A 绘制圆弧形 svg animate&#xff1a;制作波浪动画&#xff0c;为了波浪动画效果自然&#xff0c;设置values关键点       attributeName&#xff1a;变化属性名 dur&#xff1a;动画时间 repeatCount&a…

使用WildFly 8在Java EE7中自举Apache Camel

从Camel版本2.10开始&#xff0c;支持CDI&#xff08;JSR-299&#xff09;和DI&#xff08;JSR-330&#xff09;。 这为在Java EE容器中以及独立Java SE或CDI容器中开发和部署Apache Camel项目提供了新的机会。 是时候尝试一下并熟悉它了。 骆驼到底是什么&#xff1f; 骆驼是…

好东西要分享

目录 矢量图标库$\text{pic}$图论神器$\text{bzoj}$离线题库打字速度表情包PPP矢量图标库 个人jio的这个阿里巴巴矢量图标库蛮不错的 上面这张就是去上面的网站找的。 $\text{pic}$ 来wallpaper abyss找点好康的图片吧。 图论神器 画图 $\text{bzoj}$离线题库 $\text{bzoj}$离线…