您的位置:首页 > 运维架构

INotifyPropertyChanged接口

2015-11-19 14:47 323 查看


实现INotifyPropertyChanged接口

官方解释:INotifyPropertyChanged 接口用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知。官方解释的很模糊,估计是个人看了都不知道到底什么时候需要实现INotifyPropertyChanged接口.小梦通过实际测试给出明确结论:

首先:OneTime模式:毫无意义,因为它的绑定只有初始时候绑定一次,根本谈不上改变!自然也就谈不上实现INotifyPropertyChanged接口.

然后是OneWay模式:我们知道OneWay模式的含义是:绑定源的每一次变化都会通知绑定目标,但是绑定目标的改变不会改变绑定源.当绑定源的数据实体类没有实现INotifyPropertyChanged接口时,当我们改变了数据源,我们会发现绑定目标的UI上的相应的数据不会立即变化.所以这时候就需要我们来实现INotifyPropertyChanged接口.

最后是TwoWay模式:在TwoWay模式下,当绑定源的数据实体类没有实现INotifyPropertyChanged接口时,我们发现.控件的更改会让数据源立即发改变,但是改变数据源,绑定目标控件却不会立即发生改变!所以当我们需要数据源改变时相对应的UI立即改变时,就需要实现INotifyPropertyChanged接口.

总之:就是当数据源改变并需要UI立即改变时我们需要实现INotifyPropertyChanged接口.

我们可以通过这个示例来明确的体会这一点:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<StackPanel>

<TextBox Header="编号"
Text="{Binding
ID,Mode=OneTime}"
Name="tbxID" ></TextBox>

<TextBox
Header="书名"
Text="{Binding
Title,Mode=OneWay}"
Name="tbxTitle"
></TextBox>

<TextBox Header="价格"
Text="{Binding
Price,Mode=TwoWay}"
Name="tbxPrice"
></TextBox>

<Button
Content="通过数据源修改控件的值" Click="Button_Click"></Button>

<Button
Content="直接修改控件的值"
Click="Button_Click_1"
/>

<Button
Content="通过控件修改数据源的值"
Click="Button_Click_2"
/>

</StackPanel>

后台代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

namespace
INotifyPropertyChangedDEMO

{

///
<summary>

///
可用于自身或导航至 Frame 内部的空白页。

///
</summary>

public
sealed
partial
class
MainPage
:
Page

{

Book
book
=
new
Book();

public
MainPage()

{

this.InitializeComponent();

this.NavigationCacheMode
=
NavigationCacheMode.Required;

book.ID
=
0;

book.Title
=
"ASP.NET 开发手册";

book.Price
=
40;

st.DataContext
=
book;

}

private
void
Button_Click(object
sender,
RoutedEventArgs
e)//通过修改数据源修改控件的值

{

book.ID
=
100;

book.Price
=
50;

book.Title
=
"SL开发手册";

}

private
async
void
Button_Click_1(object
sender,
RoutedEventArgs
e)//显示数据源的值

{

await
new
MessageDialog(book.ID.ToString()
+
" "
+
book.Title.ToString()
+
" "
+
book.Price.ToString()).ShowAsync();

}

public
class
Book
:
INotifyPropertyChanged

//INotifyPropertChanged 接口定义了一个当属性值更改时执行的事件,事件名称为PropertyChanged。

//这个是在继承这个接口的类必须要实现的事件

{

private
int
_id;

public
int
ID

{

get
{
return
_id;
}

set

{

_id
=
value;

//NotifyPropertyChange("ID");

}

}

private
string
_title;

public
string
Title

{

get
{
return
_title;
}

set

{

_title
=
value;

//NotifyPropertyChange("Title");

}

}

private
double
_price;

public
double
Price

{

get
{
return
_price;
}

set

{

_price
=
value;

//NotifyPropertyChange("Price");

}

}

public
event
PropertyChangedEventHandler
PropertyChanged;

//PropertyChangedEventArgs类型,这个类用于传递更改值的属性的名称,实现向客户端已经更改的属性发送更改通知。属性的名称为字符串类型。

private
void
NotifyPropertyChange(string
propertyName)

{

if
(PropertyChanged
!=
null)

{

//根据PropertyChanged事件的委托类,实现PropertyChanged事件:

PropertyChanged(this,
new
PropertyChangedEventArgs(propertyName));

}

}

}

}

}

大家运行这个示例可以明显体会INotifyPropertyChanged接口的作用.


如何实现INotifyPropertyChanged接口

上面示例的INotifyPropertyChanged接口的实现方式是最常见和最普遍的.

我们可以利用CallerMemberNameAttribute特性来简化一下,这个特性可以根据调用方来决定传入哪个属性的名字.:

1

2

3

4

5

6

protected
void
OnPropertyChanged([CallerMemberName]
string
propertyName
=
null)

{

var
eventHandler
=
this.PropertyChanged;

if
(eventHandler
!=
null)

eventHandler(this,
new
PropertyChangedEventArgs(propertyName));

}

这样我们在调用时可以这样调用:

NotifyPropertyChange(“ID”) 改为:OnPropertyChanged();


INotifyPropertyChanged接口的最佳实现方式:

这个所谓的最佳实现方式 是channel 9的视频中说的,实现方式如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public
class
ModelBase
:
INotifyPropertyChanged

{

public
event
PropertyChangedEventHandler
PropertyChanged;

protected
bool
SetProperty<T>(ref
T
storage,
T
value,
[CallerMemberName]
String
propertyName
=
null)

{

if
(object.Equals(storage,
value))
return
false;

storage
=
value;

this.OnPropertyChanged(propertyName);

return
true;

}

protected
void
OnPropertyChanged([CallerMemberName]
string
propertyName
=
null)

{

var
eventHandler
=
this.PropertyChanged;

if
(eventHandler
!=
null)

eventHandler(this,
new
PropertyChangedEventArgs(propertyName));

}

}

相应的调用方式进一步简化:

1

2

3

4

5

6

7

8

private
string
name;

public
string
Name

{

get
{
return
name;
}

set

{
this.SetProperty(ref
this.name,
value);
}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息