這樣一來F5執行,按下Button後,Slider的滑桿也會跟著改變了!
可以看到我們讓MyDataContext繼承了INotifyPropertyChanged,然後定義了PropertyChanged事件,並實作一個OnPropertyChanged方法用來呼叫這個事件。然後在MyValue的Setter中,每當MyValue改變時,就呼叫OnPropertyChanged,以觸發PropertyChanged事件。而事實上,當我們在XAML中設定 Slider.Value = "{Binding MyValue}" 時,WPF就會自動幫我們把Slider註冊給PropertyChanged事件了,因此當事件引發時,Slider才會接到通知要更新屬性值。
Slider.Value = "{Binding MyValue}"
有了以上的觀念後,我們便可以實現控件與資料環境的雙向資料綁定了。
雖然現在可以利用INotifyPropertyChanged來通知視窗更新,然而這樣做每個被綁定的屬性都需要在Setter裡面呼叫OnPropertyChanged()方法,導致每個屬性都必須完整的定義,而不能用 Auto屬性 來簡化定義。
幸好,現在已經有 Fody.PropertyChanged 這個套件可以幫我們自動寫入代碼,只要安裝此套件,所有的Auto屬性它都可以幫你在Setter中自動注入OnPropertyChanged()語句。那麼,要怎麼使用Fody.PropertyChanged套件呢?最簡單的方式就是透過NuGet來安裝。
首先,在專案右鍵點選「管理NuGet套件」:
目的是為了要告訴Fody引擎我們需要使用哪一項功能。這樣就大功告成啦! 接下來我們可以把原本的MyDataContext簡化成這樣:
可以看到Fody套件讓我們的代碼變的非常簡潔,同時執行結果與原先完全一樣!
抱歉請問一下, 這邊我搞不太懂儲存變數的記憶體是哪時候被 allocate的.
MyDataContext 是class, 不是instance, 而程式從頭到尾沒看到哪邊new了instance來儲存 MyValue.
是否當xaml 寫
時, 就已經隱含new了一個 myDataContext 實體, 來儲存 MyValue?
還是說, 實際上沒有new myDataContext實體, 而是宣告 slider.value, 只是這個 value 數值變化時, 會呼叫 MyDataContext 的OnPropertyChanged來處理訊息?
若是這樣(呼叫MyDataContext 的 function pointer), 那是否代表編譯時, 已經把 MyDataContext 的OnPropertyChanged 當做static 處理?
會問這個問題, 是因為我大部分時候只想做簡單的 MainWindow的 global 變數 (ex. int myAge)的Data Binding. (MainWindow的 global變數 跟UI 做雙向綁定)
但MainWindow是有真正 instance, 所以 myAge 很明確指到某個記憶體位置. 但上面的範例, MyDataContext 沒有instance, 如果數值是儲存在slider裡面, 那當我想把 slider的 value跟 myAge 綁定時, 究竟資料是儲存在 myAge, 還是儲存在slider.value? 總不可能存兩份再來同步吧?
先謝謝您.
當xaml 中宣告MyDataContext就相當於在代碼中new MyDataContext囉。不只是這個,其他控件如Grid, Window等也是。這些class的instance 都是在MainWindow的constructor 裡呼叫InitializeComponent()來完成的。
當有Data Binding時,WPF會把互相綁定的物件和屬性名稱註冊到WPF內部,當有一方數值變化時就去更新另一方,過程中沒有涉及static 喔。
而你舉例的slider.value與myAge是兩方都各自存各自的資料再來同步的喔,同步的方式就是透過呼叫OnPropertyChanged。不然你想如果從頭到尾只有一份資料的話,自然也不需要呼叫OnPropertyChanged了吧?
希望這樣有解答你的疑惑
讚 Liked by 1 person