在前面兩篇文章中分别使用了TemplatePart及VisualState的方式實作了相同的功能,其中明顯VisualState的方式更靈活一些。如果遇到這種情況通常我更傾向使用VisualState。不過在實際應用中這兩種實作方式并不是互斥的,很多模闆化控件都同時使用這兩種方式,
使用VisualState有如下好處:
代碼和UI分離。
可以更靈活地擴充控件。
可以使用Blend輕松實作動畫。
并不是說VisualState好處這麼多就一定要用VisualState實作所有功能,下面這些情況我會選擇使用TemplatePart:
需要快速實作一個控件。
某個行為時固定的,不需要擴充。
需要在代碼中操作UI,譬如Slider或ComboBox。
為了強調某個部件是控件必須的。
為了隐藏實作細節,限制派生類或ControlTemplate修改重要的邏輯。
其中,使用TemplatePart産生的擴充性問題是我謹慎使用這種方案的最大因素。
除了VisualState,TemplatePart的功能也常常會被TemplateBinding代替。前面的例子展示了使用VisualState在UI上的優勢,這次用另一個控件DateTimeSelector來讨論使用TemplatePart在擴充性上的其它問題。
DateTimeSelector組合了CalendarDatePicker和TimePicker,用于選擇日期和時間(SelectedDateTime)。它的XAML如下:
代碼如下:
可以看出,DateTimeSelector通過監視CalendarDatePicker的DateChanged和TimePicker的TimeChanged來改變SelectedDateTime的值。
DateTimeSelector的代碼很簡單,控件也工作得很好,但如果某天需要将CalendarDatePicker 替換為DatePicker或某個第三方的日期選擇控件,DateTimeSelector就無能為力了,既不能通過修改ControlTemplate,也不能通過繼承來達到目的。
通常在建構這類控件時應先考慮它的資料和行為,而不關心它的UI。DateTimeSelector最核心的功能是通過選擇Date和Time得出組合起來的DateTime,那麼就可以先寫出如下的類:
控件的代碼并不清楚ControlTemplate中包含什麼控件,它隻關心自己的資料。
XAML中通過綁定使用這些資料。

這裡給出了兩個Style,分别使用了CalendarDatePicker 和DatePicker ,通過TwoWay Binding通路DateTimeSelector2中的Date屬性。如果你的TemplatedControl需要有良好的擴充能力,可以嘗試使用這種方式。