WPF提供了很多類,當建立一個自訂元素時,你可以從這些類中派生。圖9-1顯示了一組可能作為類——可能是合適的基類,並且說明了他們之間的繼承關係。注意到,這決不是完整的繼承關係圖,只是簡單的顯示了一些你應該考慮的可能的基類。
無論你選擇了哪一個基類,你的元素都會直接或間接地從FrameworkElement派生。這將提供routing事件,進階屬性處理,動畫,資料繫結,外觀上的支援,樣式,以及邏輯樹狀結構的整合。
派生於FrameworkElement並不是絕對的需要。第7章討論了底層可視化圖形API,雖然該章的樣本派生自FrameworkElement,你也可以直接派生於Visual,當使用底層繪圖API的時候。然而,如果你這麼做了,你將會損失由FrameworkElement提供的全部服務。對派生於底層的元素,你只能在特別專業的環境使用到。
圖9-1
直接派生自FrameworkElement,對於一個被設計為組合到其他元素的元素而言,是恰當的。例如,考慮一個綁定到資料來源而且產生資料圖表的元素。你可能使之派生自Control。儘管如此,未經加工的圖形繪製的元素,通常協力於其他元素如TextBlock,從而為這個圖形和其軸提供標籤。因此,將graph分成圖形繪製可能是有意義的,這將合并到一個外觀中,包含著任意數量的不同控制項。
將一個控制項放在另一個控制項的模板內部是可行的。但是一旦你發現純粹是在寫一個自訂控制項,並放在另一個控制項的模板內,你可能需要回顧一下你選擇的基類了。
如果你寫一個表現自訂外觀邏輯的元素,你應該派生於Panel,從而與內嵌外觀元素保持一致。
如果你寫一個包著另一個元素的元素——在某些方面的增強,要考慮派生於Decorator。很多內嵌元素都是派生於Decorator。例如,Border,在元素的外面添加了一個邊框;還有Viewbox,可以自動調整被其包著的元素,填充有效空間。如果你希望提供一種封裝器,在內容外添加功能,要考慮派生於Decorator。
如果你的元素提供了行為,或支援使用者互動動作——不能使用內嵌組件,這時派生於Control就是恰當的了,以直接或間接的方式。例如,如果你想製作一個互動圖表組件,使用者可以在上面點擊圖表中的資料項目來檢查它們,或者放大,這可以被典型地寫為一個控制項(同時可能要使用你先前寫的表現底層映像的元素)。
Control提供了很多衍生類別,增強了基礎控制項的功能性。如果你寫了一個控制項,提供了空白地區,使用者可以在上面防止一些內容(如一個標題),你應該派生於ContentControl,這個基類提供了支援內容模型的控制項。如果你的控制項支援在頭標題以及主地區(如分頁TabPage)的中的內容,要考慮派生於HeaderedContentControl。
如果你需要表現多個子項目,首先要考慮ListBox和資料繫結以及資料樣式的聯合是否滿足你的需求。資料繫結和樣式支援WPF的ListBox處理寬範圍的情境,這些都是Win32和Windows Forms的ListBox所不適合的。一旦你需要額外的功能——內嵌的清單控制項並不支援,你應該考慮派生於你的自訂元素類型,如Selector或其基類,如ItemControl。ItemControl對包含了清單項目的控制項提供了基本支援,包括可選的資料繫結功能。Selector增強了跟蹤當前一個或一組選項的功能。