




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、WPF培訓屬性和事件屬性的來龍去脈類的作用只是將散落在程序中的變量和函數(shù)進行歸檔封裝并控制對它們的訪問而已。被封裝在類中的變量稱為字段,它表示的是類或實例的狀態(tài);被封裝在類里的函數(shù)叫做方法,它表示的是類或實例的功能。我們可以使用Private、Public來控制字段或方法的可訪問性:是否使用static關鍵字來修飾字段或者方法則決定了字段或方法是對類有意義還是對類的實例有意義。C#語言規(guī)定:對類有意義的字段或方法用static關鍵字修飾,稱為靜態(tài)成員。通過類名+訪問操作符就可以訪問到他們;對類的實例或方法有意義的字段不用static關鍵字修飾,稱為非靜態(tài)成員或者實例成員。屬性的來龍去脈現(xiàn)在讓我
2、們來看看屬性是怎么演變出來的。字段被封裝在實例里,要么能被外接訪問,要么不能,如下左圖所示。這種直接把數(shù)據暴露給外界的做法很不安全,很容易就把錯誤的值寫入字段。如果在每次寫入字段的時候先判斷一下值的有效性又會增加冗余的代碼并違反了面向對象要求的“高內聚”的原則,我們希望對象自己有能力判斷將被寫入值是否正確,于是,程序員仍然把字段定義為private,而使用一對非private方法來包裝它。在這個方法中,一個以Set為前綴負責判斷數(shù)據的有效性并寫入數(shù)據。另一個以Get為前綴的負責把字段里的數(shù)據讀出來。如下右圖:屬性的來龍去脈微軟進一步對Get/Set這對方法進行了封裝合并成了屬性(Propert
3、y)。使用屬性的時候,格式上很像使用非private字段,保證了語義上的順暢,同時又不失Get/Set方法的安全性,代碼也變的更加緊湊,自動提示菜單也短了很多,可謂一舉多得。使用屬性,Student類就可以改成這樣: public class Student public string Name get; set; private int _age; public int Age get return _age; set _age = value; 這種.netFrameWork中屬性又稱之為CLR屬性(CLR, Common Language Runtime)。我們既可以說CLR屬性是pri
4、vate字段的安全訪問包裝,也可以說一個private字段在后臺支持(back)一個CLR屬性。這個模式可以用右圖進行表示:依賴屬性依賴屬性在WPF中,微軟將屬性又往前推了一步,推出了“依賴屬性”這個新概念。簡言之,依賴屬性就是可以自己沒有值,并能夠通過Binding從數(shù)據源獲取值(依賴在別人身上)的屬性。擁有依賴屬性的對象被稱為“依賴對象”。與傳統(tǒng)的CLR屬性和面向對象相比依賴屬性有很多新穎之處,其中包括: 節(jié)省實例對內存的開銷。 屬性值可以通過Binding依賴在其它對象上。傳統(tǒng)的.NET開發(fā)中,一個對象所暫用的內存空間在調用New操作符進行實例化的時候就已經決定了,而WPF允許對象在被創(chuàng)
5、建的時候并不包含用于存儲數(shù)據的空間(即字段所占用的空間)、只保留在需要用到數(shù)據的時候能夠獲得默認值。借用其它對象的數(shù)據或者實時分配空間的能力-這種對象稱為依賴對象而他這種實時獲取數(shù)據的能力則依靠依賴屬性來實現(xiàn)。在WPF開發(fā)中,必須使用依賴對象作為依賴屬性的宿主,使二者結合起來,才能形成完整的Binding目標被數(shù)據所驅動依賴屬性依賴屬性在WPF系統(tǒng)中,依賴對象的概念被DependencyObject類所實現(xiàn)。依賴屬性的概念則由DependencyProperty來實現(xiàn)。DependencyObject具有GetValue和SetValue兩個方法。這兩個方法都以DependencyProper
6、ty作為參數(shù),GetValue是通過DependencyProperty獲取對象;SetValue通過DependencyProperty對象存儲值-正是這兩個方法把DependencyObject和DependencyProperty緊密的結合在了一起。 DependencyObject是WPF系統(tǒng)中相當?shù)讓拥囊粋€基類,如左圖所示。從這棵繼承樹上可以看出,WPF的所有控件都是依賴對象。WPF的類庫在設計的時候充分利用了依賴屬性的優(yōu)勢,UI控件的絕大多數(shù)屬性已經依賴化了。依賴屬性聲明依賴屬性聲明DependencyProperty必須以DependencyObject作為宿主,借助它的SetV
7、alue和GetValue進行記錄和讀取。因此,想使用自定義的DependencyProperty,宿主一定是DependencyObject的派生類。DenpendencyProperty實例聲明特點很鮮明-引用變量由public static readonly三個修飾符進行修飾,實例并非使用new操作符得到而是使用DependencyProperty.Register方法實現(xiàn),代碼如下: public class StudentDp : DependencyObject public static readonly DependencyProperty NameProperty = Dep
8、endencyProperty.Register(Name, typeof(string), typeof(StudentDp); 下面分析一下這三個參數(shù):第一個參數(shù)為string類型,用這個參數(shù)指明哪個CLR屬性作為這個依賴屬性的包裝器,或者說此依賴屬性支持的是哪個CLR屬性。第二個參數(shù)用來指明此依賴屬性用來存儲什么類型的值。第三個參數(shù)用來指明此依賴屬性的宿主是什么類型,或者說DependencyProperty.Register方法將這個依賴屬性關聯(lián)到哪個類型上。依賴屬性使用依賴屬性使用理解了依賴屬性聲明變量和創(chuàng)建實例的過程,我們可以嘗試使用它了。依賴屬性首先是屬性,所以我們先嘗試用這個屬
9、性來存儲值并把存儲的值順利的讀取出來。Xaml部分: C#部分: private void button1_Click(object sender, RoutedEventArgs e) StudentDp stu = new StudentDp(); stu.SetValue(StudentDp.NameProperty, textBox1.Text); textBox2.SetValue(TextBox.TextProperty, stu.GetValue(StudentDp.NameProperty); 上面的例子,依賴屬性做為“屬性”的功能已經體現(xiàn)出來,但是,如何體現(xiàn)出依賴呢?讓我們先
10、看下面一個例子。依賴屬性使用依賴屬性使用 StudentDp stu; public DependencyCtrl() InitializeComponent(); StudentDp stu = new StudentDp(); Binding b = new Binding(Text) Source = textBox1 ; BindingOperations.SetBinding(stu, StudentDp.NameProperty, b); private void button1_Click(object sender, RoutedEventArgs e) textBox2.Se
11、tValue(TextBox.TextProperty, stu.GetValue(StudentDp.NameProperty); 依賴屬性包裝依賴屬性包裝看完這幾個例子,相信大家已經理解了依賴屬性的使用方法。但是現(xiàn)在我們使用依賴屬性依靠SetValue和GetValue兩個方法進行外界的暴露,而且在使用GetValue的時候還要做一次數(shù)據類型轉換,因此,大多數(shù)情況下我們會對依賴屬性做一個CLR屬性外包裝: public string Name get return (string)GetValue(NameProperty); set SetValue(NameProperty, valu
12、e); 第4個參數(shù)的類型是PropertyMetaData類。第4個參數(shù)是給依賴屬性的DefaultMetaData屬性賦值。顧名思義,DefaultMetaData屬性是為了向依賴屬性的調用者提供一些基本信息,這些信息包括:CoerceValueCallBack:依賴屬性值被強制改變的時候該委托會被調用,此委托可以關聯(lián)一個響應函數(shù)。DefaultValue:依賴屬性未被顯示賦值的時候,若讀取之則獲得此默認值,不設此值會拋出默認值。IsSealed:控制PropertyMetaData的屬性值是否可以更改,默認值為true;PropertyChangedCallBack:依賴屬性的值被更改的時
13、候該委托會被調用,此委托可以關聯(lián)一個影響函數(shù)。附加屬性附加屬性理解了依賴屬性以后,再來看看附加屬性。顧名思義,附加屬性就是說一個屬性本來不屬于某個對象,但由于某種需求后來又被附加上了。也就是說把對象放入一個特定的環(huán)境對象才能擁有該屬性,這種屬性就是附加屬性。例如TextBox控件放在Grid里面讓Grid為它附加Column屬性。放在Canvas里面就讓Canvas為它附加上Top和Left屬性。放在DockPanel里面,就讓DockPanel為它附加Dock屬性??梢?,附加屬性的作用就是將屬性于宿主解耦,讓數(shù)據類型設計更加靈活。理解了附加屬性的含義,我們開始研究附加屬性的聲明,注冊和使用。
14、附加屬性的本質就是依賴屬性。二者僅在包裝器和注冊上有一點區(qū)別。 public class School:DependencyObject obj) return (int)obj.G public static int GetGrade(DependencyObject etValue(GradeProperty); public static void SetGrade(DependencyObject obj, int value) obj.SetValue(GradeProperty, value); public static readonly DependencyProperty G
15、radeProperty = DependencyProperty.RegisterAttached(Grade, typeof(int), typeof(School), new PropertyMetadata(0);使用附加屬性使用附加屬性前面我們定義了個附加屬性,但是如何消費School的GradeProperty呢?請看一下代碼: StudentDp st1 = new StudentDp(); School.SetGrade(st1, 15); int grade = School.GetGrade(st1);現(xiàn)在我們已經知道如何在XAML和C#代碼中直接為附加屬性賦值,不過別忘了
16、,附加屬性的本質是依賴屬性-附加屬性也可以使用Binding依賴在其它對象的數(shù)據上。如: 事件事件就像屬性系統(tǒng)在WPF中得到了升級、進化為依賴屬性一樣,事件系統(tǒng)在WPF也得到了升級-進化成為了路由事件(Routed Event),并在其基礎上衍生出命令傳遞機制。這些機制在很大程度上減少了對程序員的束縛,讓程序的設計和實現(xiàn)更加的靈活,模塊之間的耦合度也進一步降低。路由一詞的意思大概是這樣:起點和終點間有若干個中轉站。從起點出發(fā)后經過每個中轉站時要做出選擇,最終以最快的路徑形式到達終點。因為WPF的路由環(huán)境是是UI組件樹,下面我們主要來研究一下這棵組件樹:一種叫邏輯元素樹,一種叫可視元素樹。前面我
17、們見的所有樹形結構都是LogicTree;LogicTree最顯著的特點就是完全有布局控件和控件構成,換句話說,每個節(jié)點不是布局控件就是控件。那么什么是VisualTree呢?我們知道,如果把一個樹葉放在顯微鏡下觀察,你會發(fā)現(xiàn)這片葉子也像一棵樹-有自己的基部并向上生長出多級分叉。在WPF的Logic Tree上,扮演葉子的一般都是控件。如果我們把WPF中的控件也放在顯微鏡下觀察,你會發(fā)現(xiàn)WPF控件本身也是一顆由更細微級別的組件組成的樹。事件的來龍去脈事件的來龍去脈事件的前身是消息,微軟把消息機制封裝成了更容易讓人理解的事件模型。事件模型隱藏了消息機制的很多細節(jié),讓程序開發(fā)變的簡單。繁瑣的消息驅
18、動機制在事件模型中被簡化為了3個關鍵點:事件的擁有者:即消息的發(fā)送者。事件的宿主可以在某些條件下激發(fā)它擁有的事件,即事件被觸發(fā)。事件被觸發(fā)則消息被發(fā)送。事件的響應者:即消息的接收者、處理者。事件接收者使用其事件處理器(EventHandler)對事件做出響應。事件的訂閱關系:事件的擁有者可以隨時激發(fā)事件,但事件發(fā)生后會不會得到響應要看有沒有事件響應者,或者說要看這個事件是否被關注。路由事件路由事件為了降低由事件訂閱帶來的耦合度和代碼量,WPF推出了路由事件機制。路由事件的擁有者和事件響應者之間則沒有直接顯示的訂閱關系,事件的擁有者只負責激發(fā)事件,事件將由誰響應它并不知道,事件的響應者則安裝有事
19、件偵聽器,針對某類事件進行偵聽。當有某類事件傳遞至此時事件響應者就使用事件處理器來響應事件并決定事件是否可以繼續(xù)傳遞。如下代碼,當單擊buttonLeft時,Button.Click事件就會沿著buttonLeft-CanvasLeft-gridA-gridRoot-Window線路傳遞。自定義路由事件自定義路由事件為了方便程序間對象之間的通訊常需要我們自己定義一些路由事件。創(chuàng)建自定義路由事件大體分為3個步驟:聲明并注冊路由事件。為路由事件添加CLR事件包裝。創(chuàng)建可以激發(fā)路由事件的方法。定義路由事件和定義依賴屬性的手法極為相似-為你的類聲明一個public static readonly修飾的
20、RoutEvent類型字段,然后用EventManager類的RegisterRoutedEvent方法進行注冊。為事件添加CLR事件包裝是為了讓路由事件暴露的像一個傳統(tǒng)的直接事件,如果不關注底層實現(xiàn),程序員不會感覺到它與傳統(tǒng)直接事件的區(qū)別,仍然可以使用操作符(+=)為事件添加處理器和使用操作符(-=)移除不在使用的事件處理器。為路由添加CLR事件包裝的代碼與使用CLR屬性包裝依賴屬性的代碼格式非常接近,只是關鍵字get和set被替換為add和remove。當使用操作符+=添加對路由事件的偵聽處理時,add分支的代碼會被調用;當使用-=操作符移除對事件的偵聽處理時,remove分支的代碼會被調
21、用。自定義路由事件自定義路由事件最重要的是了解EventManager的RegisterRoutedEvent的4個參數(shù)。 第一個參數(shù)是一個String類型,被稱為路由事件的名稱,按微軟的建議,這個字符串應該于RountEvent變量的前綴和CLR事件包裝器名稱一致。第二個參數(shù)為路由事件的策略。WPF路由事件有三種路由策略:Bubble,冒泡式:路由事件由事件激發(fā)者出發(fā)向它的上一層容器一層一層路由,直至最外層的容器(Windows或Page)。Tunnel,隧道式:事件的路由剛好和冒泡式相反,是由樹的樹根向事件激發(fā)者移動,這就想當于在樹根和目標控件之間挖了一條隧道,事件只能沿著隧道移動,所以稱
22、為“隧道式”。Direct,直達式:模仿CLR直接事件,直接將事件消息送達事件處理器。第三個參數(shù)用于指定事件處理器的類型。事件處理器的返回值類型和參數(shù)列表必須與此參數(shù)指定的委托保持一致,不然會導致在編譯的時候報異常。第四個參數(shù)用于指定路由事件的宿主(擁有者)是哪個類型。與依賴屬性類似,這個類型和第一個參數(shù)共同參與一些底層算法且產生這個路由事件的Hash Code并被注冊到程序的路由事件列表中。自定義路由事件自定義路由事件RoutedEventArgs有一個bool類型的屬性Handled,一旦這個屬性被賦值為true,就表示“路由事件”已經處理了。那么路由事件也就不必在往下傳遞了。注意:注意:
23、路由事件將程序中的組件進一步解耦(比用直接事件傳遞還要松散),使程序員可以更自由的編寫代碼、實現(xiàn)設計。這里有兩點經驗與大家分享: 很多類的事件都是路由事件,如TextBox的TextChanged事件、Binding的SourceUpdated事件等。所以在用這些類型的時候不要墨守傳統(tǒng)的.net編程帶來的習慣,要發(fā)揮自己的想象力,讓程序結構更加合理、代碼更加簡潔。 路由事件雖好,但也不能濫用。舉個例子,如果讓所有的Button(包括組件里的Button)的Click事件都傳遞到最外層窗體,讓窗體捕捉并處理它,那么程序的架構就變的毫無意義。正確的辦法是,事件該由誰來捕捉處理,傳到這個地方時就應該處理掉。RoutedEventArgs的的Source和和OriginSource路由事件是經過VisualTree向上傳遞的。VisualTree和LogicTree的本質區(qū)別就是:LogicTree的葉子節(jié)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 刨冰店加盟合同范本
- 出境旅游協(xié)議合同范本
- 出售養(yǎng)殖大院合同范本
- 加盟商家合同范本
- 共享專機采購合同范本
- 關于工程維護合同范本
- 綜合整治土地平整施工方案
- 劇本殺儲值卡合同范本
- 買賣叉車合同范本
- 分紅合同范本
- 中小學領導班子包級包組包班制度
- 汽車掛靠經營合同協(xié)議書模板
- 基坑土方開挖專項施工方案(完整版)
- 電網工程設備材料信息參考價(2024年第四季度)
- 2025年江蘇農牧科技職業(yè)學院高職單招職業(yè)技能測試近5年??及鎱⒖碱}庫含答案解析
- 數(shù)據中心運維服務投標方案(技術標)
- 瑞幸對賭協(xié)議
- 幼兒園一日活動流程教師培訓
- 2024-2025學年山東省濰坊市高一上冊1月期末考試數(shù)學檢測試題(附解析)
- 征信入校園教育課件
- 《你當像鳥飛往你的山》讀書分享讀書分享筆記
評論
0/150
提交評論