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)之属性绑定

你可能感兴趣的:(属性)