在UWP中自定義控件常常會遇到這個問題:使用UserControl還是TemplatedControl來自定義控件。
繼承自UserControl。
由複數控件組合而成。
包含XAML及CodeBehind。
優點:
上手簡單。
可以在CodeBehind直接通路UI元素。
開發速度很快。
缺點:
不能使用ControlTemplate進行定制。
通常很難繼承及擴充。
使用場景:
需要快速實作一個隻有簡單功能的控件,而且無需擴充性。
不需要可以改變UI。
不需要在不同項目中共享控件。
使用UserControl的控件:
Page及DropShadowPanel都是UserControl。
繼承自Control或其派生類。
代碼和XAML分離,可以沒有XAML。
可以使用ControlTemplate。
控件庫中的控件通常都是CustomControl。
更加靈活,容易擴充。
UI和代碼分離。
較高的上手難度。
需要一個可以擴充功能的靈活的控件。
需要定制UI。
需要在不同的項目中使用。
使用CustomControl的控件:
控件庫中提供的元素,除了直接繼承自FrameworkElement的Panel、Shape、TextBlock等少數元素,其它大部分都是CustomControl。
上一篇的DateTimeSelector例子很适合讨這個問題。這個控件沒有複雜的邏輯,用UserControl的方式實作很簡單,代碼如下:
XAML:
代碼真的很簡單,不需要GetTemplateChild,不需要DefaultStyleKey,不需要Blend,熟練的話大概5分鐘就能寫好一個。
使用UserControl有這些好處:
快速。
可以直接檢視設計視圖,不需要用Blend。
可以直接通路XAML中的元素。

當然壞處也不少:
不可以通過ControlTemplate修改UI。
難以繼承并修改。
UI和代碼高度耦合。
如果控件隻是内部使用,不是放在類庫中向第三者公開,也沒有修改的必要,使用UserControl也是合适的,畢竟它符合80/20原則:使用20%的時間完成了80%的功能。
如果需要快速實作控件,又需要适當的擴充能力,可以實作一個繼承UserControl的基類,再通過UserControl的方式派生這個基類。
建立一個名為DateTimeSelectorBase的類,繼承自UserControl,其它代碼基本上照抄上一篇文章中的DatetimeSelector2,隻不過删除了構造函數中的代碼,因為不需要DefaultStyle。
然後用普通的方式建立一個UserControl,在XAML和CodeBehind中将基類改成DateTimeSelectorBase,如下所示:
這樣既可以在不同的派生類使用不同的UI,也可以使用設計視圖,結合了UserControl和TemplatedControl的優點。缺點是不可以使用ControlTemplate,而且不清楚這個控件的開發者會直覺地以為這是TemplatedControl,使用上會造成一些混亂。