1. 程式人生 > >WPF新手之將如何將一個成員變數或自定義類繫結到控制元件

WPF新手之將如何將一個成員變數或自定義類繫結到控制元件

(再次嘆一下中國的網路環境,搜出來的網頁一大堆,可有用的沒幾個,基本是大家相互轉,真正有了問題楞是找不到能解決的)

首先如果是基本型別的變數,或者是自定義的類,直接繫結到控制元件之後,控制元件只能顯示其初始值,值的改變並不能更新UI,只有以下兩種情況的繫結:
①繫結到某個控制元件的依賴屬性DependencyProperty
②繫結到定義了INotifyPropertyChanged的類(ObservableCollection就是實現了該介面)

先看DependencyProperty。
可以把任何一個CLR物件繫結為DependencyProperty。在VS2010下輸入propdp,按Tab,會生成一個模板

MyProperty就是你要繫結的成員,修改它之後按Tab,後面的自動都會改變,如:

這裡的ownerclass是擁有此成員的類名(如:class ownerclass {//...})。最後一個引數VS自動生成的有問題,因為它放入了一個引數0。實際上應該是UIPropertyMetadata(Object, PropertyChangedCallback, CoerceValueCallback, Boolean),用於設定UI中的資料更改後回撥的函式。一般刪除之或者用預設建構函式就行。如果需要它,一個簡單的定義如下:

注意這裡是靜態函式,由DependencyObject d來得到具體的通知物件。

然後在控制元件中進行繫結,如<TextBlock Text="{Binding ElementName=MainWin, Path=Test}"/>,對Test變數的使用一如普通變數。

注意:①使用DependencyProperty比INotifyPropertyChanged的方法效能要高。因為它用Hash實現,不需要反射,而且是WPF系統中相當底層的一個基類
②DependencyObjects are not marked as serializable
③The DependencyObject class overrides and seals the Equals() and GetHashCode() methods
A DependencyObject has thread affinity – it can only be accessed on the thread on which it was created。(這一點很重要,特別是當程式中用到註冊事件時,因為這些往往要開新執行緒。比如我的這個軟體中,將bool型IsNetworkAvailabe用DependencyProperty繫結到控制元件,然後註冊事件NetworkAvailabilityChanged,在NetworkAvailabilityChangedEventHandler中更新IsNetworkAvailabe值,這樣就會丟擲異常)


在需要多執行緒 中操作的繫結變數,則需要用INotifyPropertyChanged

再看如何用INotifyPropertyChanged:
這裡要將待繫結的變數包裝在一個類中:

其中test就是我們要繫結的變數。(繫結一個變數寫這麼多一堆,有點不值,我另開一篇,做一個snippet模板,用來快速生成)。

繫結時不知為何上面的繫結方法不靈了,於是換成程式碼繫結吧:

最終,在我的應用場景中,這兩者都沒能有用,我註冊了事件NetworkAvailabilityChanged,在其中去修改一個繫結到

ListBox的ObservableCollection,讓其實現UI自動更新。但是總是會引起異常,我想可能是跨執行緒的原因吧。於是我試

著用DependencyProperty繫結一個變數,在NetworkAvailabilityChanged事件中修改,還是不行,

INotifyPropertyChanged也一樣,BackgroundWorker也不行。最終沒轍,在MainWindow中開了一個DispatcherTimer來輪

詢一個普通的bool變數:

 雖說比較醜,但沒法子啊,沒這麼多精力再去整了,先讓它工作起來吧。