当前位置:   article > 正文

[WPF]INotifyPropertyChanged接口用法

inotifypropertychanged接口

先看看如下例子,不使用INotifyPropertyChanged接口的话会存在什么问题。

不使用INotifyPropertyChanged接口

在新项目中新建一个类叫做Person.cs,这个类里面有3个字段分别是姓名、年龄、爱好,然后将字段封装。代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApplication20190905B
{
    class Person
    {
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private int _age;

        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }
        private string _hobby;

        public string Hobby
        {
            get { return _hobby; }
            set { _hobby = value; }
        }
    }
}
  • 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

然后是MainWindow.xaml代码,分别使用了单向绑定和双向绑定。

<Window x:Class="WpfApplication20190905B.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="grid1">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBlock Text="单向绑定" Grid.Column="1"/>
        <TextBlock Text="双向绑定" Grid.Column="2"/>
        <TextBlock Text="姓名:" Grid.Row="1"/>
        <TextBlock Text="年龄:" Grid.Row="2"/>
        <TextBlock Text="爱好:" Grid.Row="3"/>
        <TextBox Name="txt_name1" Text="{Binding Path=Name}" Grid.Row="1" Grid.Column="1" />
        <TextBox Name="txt_name2" Text="{Binding Path=Name,Mode=TwoWay}" Grid.Row="1" Grid.Column="2" />
        <TextBox Name="txt_age1" Text="{Binding Path=Age}" Grid.Row="2" Grid.Column="1" />
        <TextBox Name="txt_age2" Text="{Binding Path=Age,Mode=TwoWay}" Grid.Row="2" Grid.Column="2" />
        <TextBox Name="txt_hobby1" Text="{Binding Path=Hobby}" Grid.Row="3" Grid.Column="1" />
        <TextBox Name="txt_hobby2" Text="{Binding Path=Hobby,Mode=TwoWay}" Grid.Row="3" Grid.Column="2" />
        <Button Name="selectButton" Content="查看属性" Grid.Row="4" Grid.Column="1" Click="selectButton_Click" />
        <Button Name="changeButton" Content="更改属性" Grid.Row="5" Grid.Column="1" Click="changeButton_Click" />
    </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

最后是MainWindow.xaml.cs代码

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;

namespace WpfApplication20190905B
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private Person person = new Person();

        public MainWindow()
        {
            InitializeComponent();
            person.Name = "蛋蛋";
            person.Age = 25;
            person.Hobby = "看AV";
            this.grid1.DataContext = person;
        }

        private void selectButton_Click(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("姓名:" + person.Name + "\t年龄:" + person.Age + "\t爱好:" + person.Hobby);
        }

        private void changeButton_Click(object sender, RoutedEventArgs e)
        {
            person.Name = "大傻";
            person.Age = 38;
            person.Hobby ="吃饭打豆豆";
        }
    }
}
  • 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

最后,因为需要用到控制台输出,所以右击项目——属性,把输出类型改为"控制台应用程序"。
在这里插入图片描述
运行效果如下,初始数据分别是"蛋蛋"、“25”、“看AV”,中间一列是单向绑定,右边一列是双向绑定。
在这里插入图片描述

通过修改目标数据来修改源数据

当我把txt_name1改成"笨笨"的时候,只要txt_name1失去焦点,txt_name2会自动更改数据。同理,txt_name2改变内容时,一旦离开焦点,txt_name1也会立马同步。所以这一步是正常的,如下
在这里插入图片描述

直接修改源数据

那么我们直接从后台修改源数据呢?我点击按钮"更改属性"按钮后,后台执行了如下代码

person.Name = "大傻";
person.Age = 38;
person.Hobby ="吃饭打豆豆";
  • 1
  • 2
  • 3

然后点击"查看属性"按钮在控制台看到源数据此时分别更新为"大傻"、“38”、“吃饭打豆豆”。但是前台这几个TextBox无论是单向绑定还是双向绑定,都没有变更。
在这里插入图片描述
所以问题就出在这里,直接修改后台的源数据时,前台的目标数据并没有及时更新。这里就需要用到INotifyPropertyChanged接口了。

使用INotifyPropertyChanged接口

把Person.cs的代码修改成如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//INotifyPropertyChanged接口需要引用这个命名空间
using System.ComponentModel;

namespace WpfApplication20190905B
{
    //实现接口
    class Person : INotifyPropertyChanged
    {
        //声明一个PropertyChangedEventHandler的对象
        public event PropertyChangedEventHandler PropertyChanged;

        //Name和Age的set方法中新增一些代码,但是为了对比,Hobby不需要新增。
        private string _name;

        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
                }
            }
        }
        private int _age;

        public int Age
        {
            get { return _age; }
            set
            {
                _age = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Age"));
                }
            }
        }
        private string _hobby;

        public string Hobby
        {
            get { return _hobby; }
            set { _hobby = value; }
        }
    }
}
  • 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

上述代码中,Person类实现了INotifyPropertyChanged这个接口,属性Name和Age都加了一点代码来实现通知,但是注意Hobby属性没有加这段代码,所以Hobby是不能实现及时更新的。

重新再运行项目,点击"更改属性"和"查看属性",会发现前台的姓名和年龄都及时同步了,而爱好依旧没变。
在这里插入图片描述
在Person.cs代码中,对象PropertyChanged仅仅是声明出来但没有实例化,实际上代码执行到TextBox控件绑定的时候,会自动订阅了这个PropertyChanged event,所以是不需要我们去手动实例化的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/567788
推荐阅读
相关标签
  

闽ICP备14008679号