文章出處

通過微軟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>


運行效果。


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()