什么是 Change Notification,为什么它很重要(译)

[我自己尝试做的翻译,呵呵]

属性改变通知
(Property Change Notification)

有关Windows窗体数据绑定的最重要的一个概念是,它是由更改通知(change notification)驱动的。也就是说,除非数据源通知Windows窗体数据绑定运行时数据已经发生了改变(通过提供一个更改事件),否则,Windows窗体不会更新一个用户界面元素(控件)。对于简单的属性对属性的绑定,数据源需要提供一个属性更改通知,这可以通过提供一个属性的“属性名”已更改事件(比如为Customer对象的Name属性提供NameChanged事件)或者实现“INotifyPropertyChanged”接口,INotifyPropertyChangedVS 2005中新增的一个接口,它可以与BindingList<T>一起使用来创建可绑定的列表(下面会有描述)

例子:不用更改通知的简单绑定

/*******************************************************************

 * 设置(使用 Visual Studio 窗体设计器):

 *

 *  添加一个 Label 控件到窗体Form (label1)

 *  添加一下代码到 Form.Load 事件处理方法中

 ******************************************************************/

 

CurrentTime currentTime = new CurrentTime();

 

/*******************************************************************

 * 绑定Label.Text (string) CurrentTime.Now

 * 注意: 当“Now”改变时Label控件将不会更新

 * 因为“Now”没有提供更改通知.

 ******************************************************************/

 

Binding binding = new Binding("Text", currentTime, "Now", true);

binding.FormatString = "MM/dd/yyyy hh:MM:ss";

 

this.label1.DataBindings.Add(binding);

 

/***********************************************************************

*设置(使用 Visual Studio 窗体设计器):

*

*  添加一个新的类文件到你的工程,叫做 "CurrentTime"

*  添加一下代码到类的实现中

**********************************************************************/

 

public class CurrentTime

{

    System.Windows.Forms.Timer      _timer;

 

    public CurrentTime()

    {

        /***************************************************************

        * 使用一个跟踪当前时间的计时器

        ***************************************************************/

       

        _timer = new System.Windows.Forms.Timer();

 

        /***************************************************************

        * 每秒钟更新一次时间

        ***************************************************************/

 

        _timer.Interval = 1000;

        _timer.Tick += delegate { this.Now = DateTime.Now; };

        _timer.Start();

    }

 

    /*******************************************************************

    * 使用一个保存当前时间的变量

    *******************************************************************/

 

    private DateTime _now = DateTime.Now;

 

    /*******************************************************************

    *没有更改通知被绑定的控件将不会被更新

    *******************************************************************/

 

    public DateTime Now

    {

        get { return _now; }

        private set

        {

            if (_now != value)

            {

                _now = value;

            }

        }

    }

}

例子:含有“属性”已更改的更改通知的简单数据绑定

/***********************************************************************

* 设置(使用 Visual Studio 窗体设计器):

* 使用和上面的例子中一样的窗体,但是改变了 “CurrentTime”类型,为“Now”属性提供了更改通知

* 这个例子使用“属性”已更改模式。Label控件的文本在这个例子中将会正确的更新

***********************************************************************/

 

public class CurrentTime

{

    System.Windows.Forms.Timer      _timer;

 

    public CurrentTime()

    {

        /***************************************************************

        *使用一个跟踪当前时间的计时器

        ***************************************************************/

       

        _timer = new System.Windows.Forms.Timer();

 

        /***************************************************************

        *每秒钟更新一次时间

        ***************************************************************/

 

        _timer.Interval = 1000;

        _timer.Tick += delegate { this.Now = DateTime.Now; };

        _timer.Start();

    }

 

    /*******************************************************************

    *使用一个保存当前时间的变量

    *******************************************************************/

 

    private DateTime _now = DateTime.Now;

 

    /*******************************************************************

    * 属性更改通知被激发当这个属性更改时,被绑定的用户界面元素将会更新

    * 这里使用的是“属性”已更改模式

    *******************************************************************/

 

    public DateTime Now

    {

        get { return _now; }

        private set

        {

            if (_now != value)

            {

                _now = value;

                OnNowChanged(EventArgs.Empty);

            }

        }

    }

 

    /*******************************************************************

    * 提供一个属性已更改事件

    *******************************************************************/

 

    public event EventHandler NowChanged;

 

    protected virtual void OnNowChanged(EventArgs e)

    {

        if (null != NowChanged)

        {

            NowChanged(this, e);

        }

    }

}

例子:含有INotifyPropertyChanged更改通知的简单数据绑定

/***********************************************************************

*设置(使用 Visual Studio 窗体设计器):

*

* 使用上个例子中一样的窗体,但使用这个版本的CurrentTime类型做了替换.

*

* 这个例子实现了 System.ComponentModel.INotifyPropertyChanged接口.

* 这个例子中的label的文本也会正确的被更新.

**********************************************************************/

 

using System.ComponentModel;

 

public class CurrentTime : INotifyPropertyChanged

{

    System.Windows.Forms.Timer      _timer;

 

    public CurrentTime()

    {

        /***************************************************************

        *使用一个跟踪当前时间的计时器

        ***************************************************************/

       

        _timer = new System.Windows.Forms.Timer();

 

        /***************************************************************

        *每秒钟更新一次时间

        ***************************************************************/

 

        _timer.Interval = 1000;

        _timer.Tick += delegate { this.Now = DateTime.Now; };

        _timer.Start();

    }

 

    /*******************************************************************

    *使用一个保存当前时间的变量

    *******************************************************************/

 

    private DateTime _now = DateTime.Now;

 

    /*******************************************************************

    *属性更改通知被激发当这个属性更改时,被绑定的用户界面元素将会更新

    *

    * 这里使用 INotifyPropertyChanged 接口

    *******************************************************************/

 

    public DateTime Now

    {

        get { return _now; }

        private set

        {

            if (_now != value)

            {

                _now = value;

                OnPropertyChanged(“Now”);

            }

        }

    }

 

    /*******************************************************************

    * 提供 INotifyPropertyChanged.PropertyChanged 事件

    *******************************************************************/

 

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected virtual void OnPropertyChanged(string propertyName)

    {

        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));

    }

 

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)

    {

        if (null != PropertyChanged)

        {

            PropertyChanged(this, e);

        }

    }

}

 

列表更改通知

当数据源是一个列表的时候(复杂的或简单的绑定列表),数据源需要通过IbindingList接口提供列表和属性2个更改通知。列表更改通知用来在一个条目从列表中移除、删除或者新增到列表的时候通知用户界面元素。一个列表上的属性更改通知用来在列表中的某一项上的一个属性(比如列表的第N个位置上的Customer实例的“Name”属性)发生更改时通知用户界面元素。Windows窗体中列表绑定的一个关键概念是,IbindingList接口既提供依据列表的更改通知,又提供基于属性的更改通知。换句话说,这是一个比较关键的地方,被绑定到一个列表的Windows窗体控件将不会监听列表中的项目提供的属性更改通知,而是,Windows窗体需要列表为它所包含的项目提供这种通知。

VS 2005之前,实现IBindingList会在列表和列表中所包含的项之间形成强耦合,因为包含的那些项需要在他们发生改变时告诉列表。在VS2005中,这通过引入BindingList<T>INotifyPropertyChanged接口得到简化。BindingList<T>是一个IBindingList的泛型实现,它可以自动的将子项的INotifyPropertyChanged事件转换到IBindingList.ListChanged事件(译者注:这里有些疑问,为什么不转换成PropertyChanged事件呢,还需要求证

注意,如果列表是通过BindingSource绑定的话,那种绑定到一个不是IBindingList的基于列表的数据源的体验可能会改善很多。

posted on 2006-12-25 21:23  零度的火  阅读(1012)  评论(0编辑  收藏  举报

导航