INotifyPropertyChanged接口的詳細說明


windows phone開發8.1:數據綁定中,我們了解了數據綁定的基本知識.今后幾篇文章會繼續深入了解數據綁定.今天我們來看在數據綁定中十分重要的INotifyPropertyChanged接口的實現.

何時實現INotifyPropertyChanged接口

官方解釋:INotifyPropertyChanged  接口用於向客戶端(通常是執行綁定的客戶端)發出某一屬性值已更改的通知。官方解釋的很模糊,估計是個人看了都不知道到底什么時候需要實現INotifyPropertyChanged接口.小夢通過實際測試給出明確結論:

首先:OneTime模式:毫無意義,因為它的綁定只有初始時候綁定一次,根本談不上改變!自然也就談不上實現INotifyPropertyChanged接口.

然后是OneWay模式:我們知道OneWay模式的含義是:綁定源的每一次變化都會通知綁定目標,但是綁定目標的改變不會改變綁定源.當綁定源的數據實體類沒有實現INotifyPropertyChanged接口時,當我們改變了數據源,我們會發現綁定目標的UI上的相應的數據不會立即變化.所以這時候就需要我們來實現INotifyPropertyChanged接口.

最后是TwoWay模式:在TwoWay模式下,當綁定源的數據實體類沒有實現INotifyPropertyChanged接口時,我們發現.控件的更改會讓數據源立即發改變,但是改變數據源,綁定目標控件卻不會立即發生改變!所以當我們需要數據源改變時相對應的UI立即改變時,就需要實現INotifyPropertyChanged接口.

總之:就是當數據源改變並需要UI立即改變時我們需要實現INotifyPropertyChanged接口.

我們可以通過這個示例來明確的體會這一點:

 <StackPanel>

       <TextBox  Header="編號" Text="{Binding ID,Mode=OneTime}" Name="tbxID"  ></TextBox>

        <TextBox Header="書名" Text="{Binding Title,Mode=OneWay}" Name="tbxTitle" ></TextBox>

       <TextBox  Header="價格" Text="{Binding Price,Mode=TwoWay}" Name="tbxPrice" ></TextBox>

     <Button Content="通過數據源修改控件的值"  Click="Button_Click"></Button>

         <Button Content="直接修改控件的值"     Click="Button_Click_1" />

        <Button Content="通過控件修改數據源的值"   Click="Button_Click_2" />

       </StackPanel>

 

后台代碼:

namespace INotifyPropertyChangedDEMO
{
    /// <summary>
    /// 可用於自身或導航至 Frame 內部的空白頁。
    /// </summary>

    public sealed partial class MainPage : Page
    {
        Book book = new Book();
        public MainPage()
        {
            this.InitializeComponent();

            this.NavigationCacheMode = NavigationCacheMode.Required;
            book.ID = 0;
            book.Title = "ASP.NET 開發手冊";
            book.Price = 40;
            st.DataContext = book;
        }
  private void Button_Click(object sender, RoutedEventArgs e)//通過修改數據源修改控件的值
        {
            book.ID = 100;
            book.Price = 50;
            book.Title = "SL開發手冊";
        }

        private async void Button_Click_1(object sender, RoutedEventArgs e)//顯示數據源的值
        {
            await new MessageDialog(book.ID.ToString() + " " + book.Title.ToString() + " " + book.Price.ToString()).ShowAsync();
        }

        public class Book : INotifyPropertyChanged
//INotifyPropertChanged 接口定義了一個當屬性值更改時執行的事件,事件名稱為PropertyChanged。
     //這個是在繼承這個接口的類必須要實現的事件

        {
            private int _id;
            public int ID
            {
                get { return _id; }
                set
                {
                    _id = value;
                    //NotifyPropertyChange("ID");
                }
            }
            private string _title;
            public string Title
            {
                get { return _title; }
                set
                {
                    _title = value;
                    //NotifyPropertyChange("Title");
                }
            }
            private double _price;
            public double Price
            {
                get { return _price; }
                set
                {
                    _price = value;
                    //NotifyPropertyChange("Price");
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            //PropertyChangedEventArgs類型,這個類用於傳遞更改值的屬性的名稱,實現向客戶端已經更改的屬性發送更改通知。屬性的名稱為字符串類型。
            private void NotifyPropertyChange(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    //根據PropertyChanged事件的委托類,實現PropertyChanged事件:
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
}

 

大家運行這個示例可以明顯體會INotifyPropertyChanged接口的作用.

 如何實現INotifyPropertyChanged接口

上面示例的INotifyPropertyChanged接口的實現方式是最常見和最普遍的.

我們可以利用CallerMemberNameAttribute特性來簡化一下,這個特性可以根據調用方來決定傳入哪個屬性的名字.:

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var eventHandler = this.PropertyChanged;
            if (eventHandler != null)
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }

 

這樣我們在調用時可以這樣調用:

 

NotifyPropertyChange("ID")  改為:OnPropertyChanged();

INotifyPropertyChanged接口的最佳實現方式:

這個所謂的最佳實現方式 是channel 9的視頻中說的,實現方式如下:

public class ModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
        {
            if (object.Equals(storage, value)) return false;
            storage = value;
            this.OnPropertyChanged(propertyName);
            return true;
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var eventHandler = this.PropertyChanged;
            if (eventHandler != null)
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }


相應的調用方式進一步簡化:

   private string name;

        public string Name
        {
            get { return name; }
            set
            { this.SetProperty(ref this.name, value); }
        }

該睡了,明天繼續!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM