C# PropertyChanged 事件-数据绑定

在.NET平台上,数据绑定是一项令人十分愉快的技术。利用数据绑定能减少代码,简化控制逻辑。

通常,可以将某个对象的一个属性绑定到一个可视化的控件上,当属性值改变时,控件上的显示数据也随之发生变化。要实现这一功能,只需要为自定义对象实现 INotifyPropertyChanged 接口即可。此接口中定义了 PropertyChanged 事件,我们只需在属性值改变时触发该事件即可。下面的例子说明如何绑定如何自定义可用于数据绑定的对象:

假设我们有自定义对象 CustomizedObject 和窗体上的 Label 控件 label1,想要将 CustomizedObject 的 Date 属性和 label1.Text 关联起来,Date 属性值会在程序运行过程当中发生变化(例如点击 Button 控件 button1),并且直接反映在 label1.Text 上。下面的代码可以实现上述功能:

using System;

using System.ComponentModel;

using System.Windows.Forms;

namespace WindowsFormsApplication1

{

    public partial class Form1 : Form

    {

        private CustomizedObject myObject;

        public Form1()

        {

            InitializeComponent();

            // 初始化CustomizedObject对象

            myObject = new CustomizedObject { Date = DateTime.Now };

            // 绑定对象的属性到label1

            label1.DataBindings.Add("Text", myObject, "Date");

        }

        private void button1_Click(object sender, EventArgs e)

        {

            // 点击按钮改变对象的属性值

            myObject.Date = myObject.Date.AddDays(1);

        }

    }

    // 自定义对象 CustomizedObject 并实现 INotifyPropertyChanged 接口

    public class CustomizedObject : INotifyPropertyChanged

    {

        private DateTime dateValue;

        // 自定义一个 Date 属性

        public DateTime Date

        {

            get { return dateValue; }

            set

            {

                dateValue = value;

                NotifyPropertyChanged("Date");

            }

        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        // 添加一个触发 PropertyChanged 事件的通用方法

        protected virtual void NotifyPropertyChanged(string propertyName)

        {

            if (PropertyChanged != null)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }

        }

         #endregion

    }

}

其实从上面的例子中可以学习到如何自定义事件,这在开发控件时十分有用且非常重要。通过观察 INotifyPropertyChanged 接口可以知道它内部有一个成员,那就是:

event PropertyChangedEventHandler PropertyChanged;

而其中的 PropertyChangedEventHandler 实质上是一个委托,明白了这一点就可以自定义事件了。

现在,开始为 Form1 自定义事件 DateChanged (事件一般是定义在控件或组件中的,这里只是为了说明其过程而没有重新定义一个控件),首先需要一个事件参数类型:

public class DateChangedEventArgs : EventArgs

{

    public DateTime OldValue { get; set; }

    public DateTime NewValue { get; set; }

}

声明一个事件处理委托

public delegate void DateChangedHandler(object sender, DateChangedEventArgs e);

我们可以将事件直接添加到Form1的定义中,但有时为了代码的通用性,可以将事件封装到一个接口中,例如:

public interface IDateChanged

{

    event DateChangedHandler DateChanged;

}

然后我们为Form1实现 IDateChanged 接口,并在button1点击时触发该事件。以下是完整代码:

using System;

using System.ComponentModel;

using System.Windows.Forms;

namespace WindowsFormsApplication1

{

    public partial class Form1 : Form, IDateChanged

    {

        private CustomizedObject myObject;

        public Form1()

        {

            InitializeComponent();           

            // 初始化CustomizedObject对象

            myObject = new CustomizedObject { Date = DateTime.Now };

            // 绑定对象的属性到label1

            label1.DataBindings.Add("Text", myObject, "Date");

            // 添加 DateChanged 事件的处理逻辑

            this.DateChanged += new DateChangedHandler(Form1_DateChanged);

       }

        private void Form1_DateChanged(object sender, DateChangedEventArgs e)

        {

            string message = string.Format(

                "DateChanged event triggered!nOldValue: {0}nNew Value: {1}",

                e.OldValue,

                e.NewValue);

            MessageBox.Show(message);

        }

        private void button1_Click(object sender, EventArgs e)

        {

            // 点击按钮改变对象的属性值并触发 DateChanged 事件

            DateChangedEventArgs ev = new DateChangedEventArgs

            {

                OldValue = myObject.Date,

                NewValue = myObject.Date.AddDays(1)

            };

            myObject.Date = ev.NewValue;

            DateChangedMethod(ev);

        }

        #region IDateChanged Members

        public event DateChangedHandler DateChanged;

        // 添加一个触发 DateChanged 事件的通用方法

        protected virtual void DateChangedMethod(DateChangedEventArgs e)

        {

            if (DateChanged != null)

            {

                DateChanged(this, e);

            }

        }

        #endregion

    }

    // 自定义对象 CustomizedObject 并实现 INotifyPropertyChanged 和 IDateChanged 接口

    public class CustomizedObject : INotifyPropertyChanged

    {

        private DateTime dateValue;

        // 自定义一个 Date 属性

        public DateTime Date

        {

            get { return dateValue; }

            set

            {

                dateValue = value;

                NotifyPropertyChanged("Date");

            }

        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        // 添加一个触发 PropertyChanged 事件的通用方法

        protected virtual void NotifyPropertyChanged(string propertyName)

        {

            if (PropertyChanged != null)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }

        }

        #endregion

    }

    // DateChanged 事件委托

    public delegate void DateChangedHandler(object sender, DateChangedEventArgs e);

    // 用于封装事件的接口

    public interface IDateChanged

    {

        event DateChangedHandler DateChanged;

    }

    // DateChanged 事件参数

    public class DateChangedEventArgs : EventArgs

    {

        public DateTime OldValue { get; set; }

        public DateTime NewValue { get; set; }

    }

}

扩展:https://www.codeprj.com/blog/50888a1.html

HK
原文地址:https://www.cnblogs.com/HarryK4952/p/14226144.html