天天看點

[UWP]了解模闆化控件(5.1):TemplatePart vs. VisualState

在前面兩篇文章中分别使用了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中通過綁定使用這些資料。

[UWP]了解模闆化控件(5.1):TemplatePart vs. VisualState

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

繼續閱讀