【转载】wpf数据绑定binding与INotifyPropertyChanged

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 = new 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, new 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 = new 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, new PropertyChangedEventArgs (info ) ) ;
            }
        }
    }
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值