zoukankan      html  css  js  c++  java
  • 【转载】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,两个窗口冲突,编译不能通过。

  • 相关阅读:
    WinForm的Chart控件画条形图
    WinForm的Chart控件画折线图
    自定义控件
    左侧收缩菜单
    数组
    C#生成随机数的三种方法
    WinForm之GDI手动双缓冲技术
    WinForm之GDI画图步骤
    WinForm GDI编程:Graphics画布类
    翻译:《实用的Python编程》08_02_Logging
  • 原文地址:https://www.cnblogs.com/fx2008/p/2423649.html
Copyright © 2011-2022 走看看