博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【转载】wpf数据绑定binding与INotifyPropertyChanged
阅读量:6330 次
发布时间:2019-06-22

本文共 5651 字,大约阅读时间需要 18 分钟。

WPF数据绑定号称是:数据变化会通过界面更新数据,这对新手而言,绝对是个误区,在我听说这句话的时候,我真是高兴,用了以后才发现其实没有那么美。要实现前面号称的特性,需要三个条件:1、进行绑定,2、绑定的来源要实现INotifyPropertyChanged接口,意思是,源改变了要去通知目标。3、目标要是依赖属性。

下面简单贴个例子。
XAML文件:

1
2
3
4
5
6
7
8
9
10
11
<Window x:Class="InotifyChangedTest.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:local ="clr-namespace:InotifyChangedTest"
   Title="Window1" Height="300" Width="300">
   
<Grid>
       
<TextBox Height="23" Margin="40,43,52,0" Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=name}"/>
       
<TextBox Height="23" Margin="40,94,52,0" Name="textBox2" VerticalAlignment="Top" Text="{Binding Path=desc}"/>
       
<Button Height="23" Margin="106,0,97,42" Name="button1" VerticalAlignment="Bottom" Click="button1_Click">Button
</Button>
   
</Grid>
</Window>

TextBox 的Text是依赖属性。

cs文件,新手问题一般都比较多,我就把所有代码都复制过来了:

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
80
81
82
83
84
85
86
87
88
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Windows
;
using
System.Windows.Controls
;
using
System.Windows.Data
;
using
System.Windows.Documents
;
using
System.Windows.Input
;
using
System.Windows.Media
;
using
System.Windows.Media.Imaging
;
using
System.Windows.Navigation
;
using
System.Windows.Shapes
;
using
System.ComponentModel
;
namespace InotifyChangedTest
{
   
/// <summary>
   
/// Interaction logic for Window1.xaml
   
/// </summary>
   
public
partial
class Window1
: Window
   
{
       
public person ps
{
get
;set
;
}
       
public Window1
(
)
       
{
            InitializeComponent
(
)
;
            ps
= person
(
)
;
           
//注意这句,指定数据源
           
this
.
DataContext
= ps
;
       
}
       
private
void button1_Click
(
object sender, RoutedEventArgs e
)
       
{
            ps
.
name
+=
"a"
;
            ps
.
desc
+=
"b"
;
       
}
   
}
//实现INotifyPropertyChanged接口,当数据改变时通知
   
public
class person
:INotifyPropertyChanged
   
{
       
public
event PropertyChangedEventHandler PropertyChanged
;
       
private
string _name
;
       
public
string name
       
{
            get
           
{
               
return _name
;
           
}
            set
           
{
               
if
(value
!= _name
)
               
{
                    _name
= value
;
                   
//改变时通知
                    prochanged
(
"name"
)
;
               
}
           
}
       
}
       
private
string _desc
;
       
public
string desc
       
{
            get
           
{
               
return _desc
;
           
}
            set
           
{
               
if
(value
!= _desc
)
               
{
                    _desc
= value
;
                   
//改变时进行通知
                    prochanged
(
"desc"
)
;
               
}
           
}
       
}
       
       
private
void prochanged
(
string info
)
       
{
           
if
(PropertyChanged
!=
null
)
           
{
               
//是不是很奇怪,这个事件发起后,处理函数在哪里?
               
//我也不知道在哪里,我只知道,绑定成功后WPF会帮我们决定怎么处理。
                PropertyChanged
(
this, PropertyChangedEventArgs
(info
)
)
;
           
}
       
}
   
}
}

前面的数源是在代码里通过this.DataContext = ps;这句话绑定的。接下来,贴两段代码,用XAML来替代这句话。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Window x:Class="InotifyChangedTest.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local ="clr-namespace:InotifyChangedTest"
   Title="Window1" Height="300" Width="300">
   
<Window.Resources>
       
<local:personContainer x:Key="myDataSource" />
   
</Window.Resources>
   
<Grid>
       
<TextBox Height="23" Margin="40,43,52,0" Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=ps.name,Source={StaticResource myDataSource}}"/>
       
<TextBox Height="23" Margin="40,94,52,0" Name="textBox2" VerticalAlignment="Top" Text="{Binding Path=ps.desc,Source={StaticResource myDataSource}}"/>
       
<Button Height="23" Margin="106,0,97,42" Name="button1" VerticalAlignment="Bottom" Click="button1_Click">Button
</Button>
   
</Grid>
</Window>

注意上面,定义了一个资源,程序的编译的时候会自动创建这个资源的实例。

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Windows
;
using
System.Windows.Controls
;
using
System.Windows.Data
;
using
System.Windows.Documents
;
using
System.Windows.Input
;
using
System.Windows.Media
;
using
System.Windows.Media.Imaging
;
using
System.Windows.Navigation
;
using
System.Windows.Shapes
;
using
System.ComponentModel
;
namespace InotifyChangedTest
{
   
/// <summary>
   
/// Interaction logic for Window1.xaml
   
/// </summary>
   
public
partial
class Window1
: Window
   
{
       
public personContainer pc
;
       
public Window1
(
)
       
{
            InitializeComponent
(
)
;
           
//这里为什么不用下面注释掉的这句,而用FindResource呢?
           
//如果用了注释的这句,那么程序编译的时候,会新建一个personContainer实例,xaml的资源也会新建实例
           
//两个实例不相同,所以就算绑定了数据,pc改变时,界面也不能更新
           
//因而需要用FindResource保证XAML和CS文件使用的是同一个实例。
           
//pc = new personContainer();
            pc
=
(personContainer
)
this
.
FindResource
(
"myDataSource"
)
;
       
}
       
private
void button1_Click
(
object sender, RoutedEventArgs e
)
       
{
            pc
.
ps
.
name
+=
"a"
;
            pc
.
ps
.
desc
+=
"b"
;
       
}
   
}
   
public
class personContainer
   
{
       
public person ps
{
get
; set
;
}
       
public personContainer
(
)
       
{
            ps
= person
(
)
;
            ps
.
name
=
"ab"
;
            ps
.
desc
=
"dd"
;
       
}
   
}
   
public
class person
:INotifyPropertyChanged
   
{
       
public
event PropertyChangedEventHandler PropertyChanged
;
       
private
string _name
;
       
public
string name
       
{
            get
           
{
               
return _name
;
           
}
            set
           
{
               
if
(value
!= _name
)
               
{
                    _name
= value
;
                    prochanged
(
"name"
)
;
               
}
           
}
       
}
       
private
string _desc
;
       
public
string desc
       
{
            get
           
{
               
return _desc
;
           
}
            set
           
{
               
if
(value
!= _desc
)
               
{
                    _desc
= value
;
                    prochanged
(
"desc"
)
;
               
}
           
}
       
}
       
private
void prochanged
(
string info
)
       
{
           
if
(PropertyChanged
!=
null
)
           
{
                PropertyChanged
(
this, PropertyChangedEventArgs
(info
)
)
;
           
}
       
}
   
}
}

注意到前后两个CS文件,在后面的CS里新建了一个类用来绑定,你会不会奇怪,为什么不像第一个例子一样,直接用WINDOW1里的PS呢,原因还是前面提到的,XAML里会对资源创建实例,所以如用把WINDOW1做为资源,XAML就会去创建WINDOW1的实例,CS也创建WINDOW,两个窗口冲突,编译不能通过。

转载于:https://www.cnblogs.com/fx2008/archive/2012/03/29/2423649.html

你可能感兴趣的文章
Jvm垃圾回收器(终结篇)
查看>>
ajax发起和收到服务器的信息
查看>>
SPOJ TTM
查看>>
HDU-2159 FATE (DP)
查看>>
1390 游戏得分(贪心)
查看>>
hdu2830(2009多校第二场) 可交换列最大矩形面积
查看>>
win7中chm无法显示
查看>>
工作杂记
查看>>
Socket的错误码和描述(中英文翻译)
查看>>
算法的乐趣 (王晓华 著)
查看>>
Windows和Linux系统下,虚拟环境安装的全面说明和详细步骤
查看>>
vue 引入bootstarp --webpack
查看>>
codeforce div 377
查看>>
表单验证
查看>>
博客突破10万写点东西
查看>>
# 2017-2018-1 20155224 《信息安全系统设计基础》第九周学习总结
查看>>
网址收藏1
查看>>
spring mvc-REST
查看>>
Java反射机制
查看>>
Selenium Web 自动化 - 项目实战环境准备
查看>>