天天看點

[UWP]了解模闆化控件(10):原則與技巧

推薦以符合以下原則的方式編寫模闆化控件:

選擇合适的父類:選擇合适的父類可以節省大量的工作,從UWP自帶的控件中選擇父類是最安全的做法,通常的選擇是Control、ContentControl、ItemsControl,也可以選擇從RangeBase、Selector中。

代碼和UI分離:通常控件的開發者不能控制最終使用者怎麼重寫ControlTemplate,盡量做到代碼和UI分離可以避免更多的異常。而且先寫完所有代碼,再用Blend實作UI,會比在代碼和UI間交錯地工作更高效。

使用依賴屬性:控件的使用者會認為所有控件的屬性都是可以綁定的,除非有特殊理由不要破壞這個約定俗成的規則。

不要實施嚴格的模版約定:模版約定指TemplatePart和TemplateVisualState,應該盡可能減少約定,在沒有遵循模版約定的任何一項時也不應該引發異常,要允許ControlTemplate的開發者可以通過删除某項TemplatePart或VisualState來屏蔽某項功能。

一個控件是否好用,很大一部分取決于名稱。好的命名能讓使用者用起來更得心應手,壞的命名隻會讓代碼更混淆。下面總結了UWP控件命名的一般模式:

根據控件實際功能命名,譬如Button。

以父類型的名字作為字尾,如RepeatButton。

使用常用的字尾,如-Control、-Box、-Item、-View、-Viewer、-Bar。

如果控件如現有控件功能相同,可以考慮使用Extend-、Advanced-、Simple-做字首;也可以使用公司名做字首,譬如ComponentOne公司的C1DataGrid。

可以使用-ex做字尾,但容易和擴充方法類混淆。

ItemsControl派生類的子元素控件要使用父元素名稱做字首、-Item做字尾,譬如ComboBox的子元素ComboBoxItem。

如果控件通過滑鼠選取内容(通常會打開一個Popup),可以使用-Picker做字尾。

盡量不要用-Panel做字尾,通常隻有繼承Panel的才會用這種方式命名,如StackPanel。但也有ControlPanel這種例外。

對于複雜的控件或控件庫項目,以下技巧可能對你有幫助。

在編寫模闆化控件時,依賴屬性最大的缺點會暴露無遺:它太複雜了。一個完整的依賴屬性定義可以有20行(屬性辨別符、屬性包裝器、PropertyChangedCallback等),而且其中一部分是靜态的,另外一部分不是,在類中将一個依賴屬性的所有部分放在一起,還是按靜态、非靜态的順序存放,這也可能引起争論。

這個系列的主旨是講解常見的模闆化控件技術,希望了解這些技術後能更輕松地構造自己的控件,對了解開源控件庫的代碼也有一定的幫助。

職業生涯中看過很多程式員都不會寫模闆化控件(畢竟大部分場景使用UserControl或修改ControlTemplate就能解決),希望這個系列可以幫到想要學習模闆化控件的開發者。

雖然寫得很長,其實已經盡量精簡文字和内容了。平時我看到很長的文章,都會“儲存到Pocket”,然後就再也沒讀過。汲取了這個教訓,這次的文章分成多篇,盡量每篇都控制在可以三五分鐘内看完。

這個系列的内容有很多來自于WPF/Silverlight的經驗,雖然有一些小出入,基本上可以用在WPF的自定義控件。

如有錯漏請指出。

<a href="https://docs.microsoft.com/zh-cn/windows/uwp/controls-and-patterns/control-templates">控件模闆</a>

<a href="https://msdn.microsoft.com/zh-cn/library/cc278068(v=vs.95).aspx">Silverlight 控件自定義</a>

<a href="https://github.com/Microsoft/UWPCommunityToolkit">UWPCommunityToolkit</a>

繼續閱讀