xaml mvvm(2)之属性绑定

通过微软INotifyPropertyChanged接口,可以实现对UI实时更新,不管是数据源或者目标对象,可以实现相互通知。

下面我们根据INotifyPropertyChanged编写一个扩展类。该类是基于C#5.0特性,这里我们介绍一下System.Runtime.CompilerServices命名空间下的CallerMemberName特性,当RaisePropertyChanged的属性名称参数为空,而通过编译器可以智能加上,可以通过反编译工具知晓,这点改进这点很人性化。注:如果开发版本framework 4.0,则需要安装KB2468871补丁或者更新framework 4.0以上版本。

为这个扩展类添加命名空间如下。

1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Diagnostics;
5 using System.Linq.Expressions;
6 using System.Reflection;
7 using System.Runtime.CompilerServices;
 1 public class ObservableObject : INotifyPropertyChanged
 2 {
 3     public event PropertyChangedEventHandler PropertyChanged;
 4     protected PropertyChangedEventHandler PropertyChangedHandler
 5     {
 6         get
 7         {
 8             return this.PropertyChanged;
 9         }
10     }
11     [Conditional("DEBUG"), DebuggerStepThrough]
12     public void VerifyPropertyName(string propertyName)
13     {
14         Type type = base.GetType();
15         if (!string.IsNullOrEmpty(propertyName) && type.GetTypeInfo().GetDeclaredProperty(propertyName) == null)
16         {
17             throw new ArgumentException("Property not found", propertyName);
18         }
19     }
20     protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
21     {
22         PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
23         if (propertyChanged != null)
24         {
25             propertyChanged(this, new PropertyChangedEventArgs(propertyName));
26         }
27     }
28     protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
29     {
30         PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
31         if (propertyChanged != null)
32         {
33             string propertyName = ObservableObject.GetPropertyName<T>(propertyExpression);
34             propertyChanged(this, new PropertyChangedEventArgs(propertyName));
35         }
36     }
37     protected static string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
38     {
39         if (propertyExpression == null)
40         {
41             throw new ArgumentNullException("propertyExpression");
42         }
43         MemberExpression memberExpression = propertyExpression.Body as MemberExpression;
44         if (memberExpression == null)
45         {
46             throw new ArgumentException("Invalid argument", "propertyExpression");
47         }
48         PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
49         if (propertyInfo == null)
50         {
51             throw new ArgumentException("Argument is not a property", "propertyExpression");
52         }
53         return propertyInfo.Name;
54     }
55     protected bool Set<T>(Expression<Func<T>> propertyExpression, ref T field, T newValue)
56     {
57         if (EqualityComparer<T>.Default.Equals(field, newValue))
58         {
59             return false;
60         }
61         field = newValue;
62         this.RaisePropertyChanged<T>(propertyExpression);
63         return true;
64     }
65     protected bool Set<T>(string propertyName, ref T field, T newValue)
66     {
67         if (EqualityComparer<T>.Default.Equals(field, newValue))
68         {
69             return false;
70         }
71         field = newValue;
72         this.RaisePropertyChanged(propertyName);
73         return true;
74     }
75     protected bool Set<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
76     {
77         return this.Set<T>(propertyName, ref field, newValue);
78     }
79 }

下面我们来继承这个类编写一个Animal类对象。在这里我们用到RaisePropertyChanged三种不同的实现方式,达到一样的绑定效果。

 1 public class Animal : ObservableObject
 2 {
 3     private string m_Cat;
 4     public string Cat
 5     {
 6         get { return m_Cat; }
 7         set { m_Cat = value; RaisePropertyChanged("Cat"); }
 8     }
 9
10     private string m_Dog;
11     public string Dog
12     {
13         get { return m_Dog; }
14         set { m_Dog = value; RaisePropertyChanged(); }
15     }
16
17     private string m_Tiger;
18     public string Tiger
19     {
20         get { return m_Tiger; }
21         set { m_Tiger = value; RaisePropertyChanged(() => this.Tiger); }
22     }
23 }

下面我们来建立model视图类。在该类中用的事件绑定和model对象实现,我们会在后续介绍。

 1 public class MainPageViewModel : Core.ViewModelBase
 2 {
 3     public MainPageViewModel()
 4     {
 5         MyAnimal = new Animal();
 6     }
 7
 8     private Animal m_MyAnimal;
 9     public Animal MyAnimal
10     {
11         get { return m_MyAnimal; }
12         set { m_MyAnimal = value; RaisePropertyChanged("MyAnimal"); }
13     }
14
15     public ICommand OKCommand
16     {
17         get
18         {
19             return new RelayCommand(() =>
20             {
21                 MyAnimal.Dog = "eating";
22                 MyAnimal.Cat = "sleeping";
23                 MyAnimal.Tiger = "hungry";
24             });
25         }
26     }
27 }

前台xaml。

 1 <Grid DataContext="{Binding Path=MainPageViewModel}">
 2     <StackPanel>
 3         <StackPanel Orientation="Horizontal">
 4             <TextBlock FontSize="25" Text="cat is:" />
 5             <TextBlock FontSize="25" Text="{Binding MyAnimal.Cat}" />
 6         </StackPanel>
 7         <StackPanel Orientation="Horizontal">
 8             <TextBlock FontSize="25" Text="dog is:" />
 9             <TextBlock FontSize="25" Text="{Binding MyAnimal.Dog}" />
10         </StackPanel>
11         <StackPanel Orientation="Horizontal">
12             <TextBlock FontSize="25" Text="Tiger is:" />
13             <TextBlock FontSize="25" Text="{Binding MyAnimal.Tiger}" />
14         </StackPanel>
15         <Button Width="60" Content="OK" Command="{Binding OKCommand}" />
16     </StackPanel>
17 </Grid>

运行效果。

xaml mvvm(2)之属性绑定

时间: 2024-11-05 22:34:02

xaml mvvm(2)之属性绑定的相关文章

xaml mvvm(1)之结构

在微软winstore.wp和silverlight中xaml是用来构建UI视图的标记语言,全名Extensible Application Markup Language.在结构上类似于html,但在本质上属于.net通用编程语言范畴. mvvm模型的实现很大程度上要归功于xaml独特的动态绑定机制,通过这种机制可以实现数据源.事件的实时绑定.如果把一个页面比作一个control,那么就对应一个model,在这个model里面存在需要绑定的事件方法.属性. 为了更好的理解mvvm的运行机制,我

【WPF】如何把一个枚举属性绑定到多个RadioButton

一.说明 很多时候,我们要把一个枚举的属性的绑定到一组RadioButton上.大家都知道是使用IValueConverter来做,但到底怎么做才好? 而且多个RadioButton的Checked和UnChecked都会触发绑定,这样就会调多次的Set. 二.目的 实现一个枚举属性绑定到多个RadioButton, 属性的Set方法不会被触发多次. 三.实现 方法大家都知道,就是利用Converter和ConevertParamter属性. 因为多个控件绑定一个属性,Checked和UnChe

WPF属性绑定实现双向变化

WPF依赖项属性可以实现属性的绑定,成功绑定之后只要修改后台绑定的属性,即可UI同步自动更新绑定的值,无需手动刷新界面:同样,前台的值变化后,通过获取绑定的属性值也可获取UI变化后的值,实现双向变化的效果.属性绑定使得UI更新非常的方便,下面分享一个小栗子说明使用的方式. 1.先做了一个有一个TextBlock和一个Button的UI,想要实现点击后TextBlock发生变化. <Window x:Class="WPFDemo.Window1" xmlns="http:

2019-11-29-WPF-依赖属性绑定不上调试方法

原文:2019-11-29-WPF-依赖属性绑定不上调试方法 title author date CreateTime categories WPF 依赖属性绑定不上调试方法 lindexi 2019-11-29 08:46:33 +0800 2019-8-2 18:44:5 +0800 WPF 在写 WPF 程序的时候会遇到依赖属性绑定了,但是值没有更新或者没有绑定上的问题,本文告诉大家可以如何调试 依赖属性不对应 在写依赖属性的时候,默认使用快捷键创建,但是如果是自己写的,需要注意引用的类以

Vue.js学习笔记:属性绑定 v-bind

v-bind  主要用于属性绑定,Vue官方提供了一个简写方式 :bind,例如: <!-- 完整语法 --> <a v-bind:href="url"></a> <!-- 缩写 --> <a :href="url"></a> 绑定HTML Class 一.对象语法: 我们可以给v-bind:class 一个对象,以动态地切换class.注意:v-bind:class指令可以与普通的class特

Ember.js 入门指南——handlebars属性绑定

本文从http://www.ibeginer.sinaapp.com迁移过来,欢迎访问原页面. 简单讲属性绑定其实就是在HTML标签内(是在一个标签的"<"和">"中使用)直接使用handlebars表达式.可以直接用handlebars表达式的值作为HTML标签中某个属性的值. 准备工作:ember generate route binding-element-attributes 1,绑定字符串 <!-- //  app/templates/b

使用注解属性绑定

大家应该知道在Spring中有一个注解@Value,他可以帮助我们来讲Spring加载的配置文件(*.perperties)文件中的信息自动的注入到我们的非静态属性中的. 一般情况下我们会这样使用: 1. 首先在Spring的配置文件中加载属性文件: ? 1 <context:property-placeholder location="classpath:component.properties"  ignore-unresolvable="true"/&g

qml中的属性绑定与赋值

浅谈qml属性绑定与赋值 属性赋值 就字面意思,赋一个值给属性 Rectangle { id:rect Component.onCompeleted:{ rect.width = 10; // 赋值 rect.height = 10; // 赋值 rect.color = "red"; // 赋值 } } 属性赋值时会发出信号,可以通过信号处理器,来为信号添加处理函数,关于信号处理器,也就是连接到同一个信号的槽函数的队列,每次为信号处理器书写处理函数时,并不会覆盖上一次书写的处理器,最

Knockoutjs实例 - 属性绑定(Bindings)之流程控制(Control flow)

一.foreach binding 使用此功能可以方便我们循环遍历输出某个数组.集合中的内容. (1).循环遍历输出数组 View Row Code 1 <script type="text/javascript" src="knockout-2.2.0.js"></script> 2   3 <table> 4      <thead> 5          <tr><th>First nam