首页 > 代码库 > xaml mvvm(2)之属性绑定
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 Dog12 {13 get { return m_Dog; }14 set { m_Dog = value; RaisePropertyChanged(); }15 }16 17 private string m_Tiger;18 public string Tiger19 {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 MyAnimal10 {11 get { return m_MyAnimal; }12 set { m_MyAnimal = value; RaisePropertyChanged("MyAnimal"); }13 }14 15 public ICommand OKCommand16 {17 get18 {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>
运行效果。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。