[UWP]了解模板化控件(5.2):UserControl vs. TemplatedControl
来源:互联网 发布:java语言培训学校 编辑:程序博客网 时间:2024/05/29 19:14
1. UserControl vs. TemplatedControl
在UWP中自定义控件常常会遇到这个问题:使用UserControl还是TemplatedControl来自定义控件。
1.1 使用UserControl自定义控件
- 继承自UserControl。
- 由复数控件组合而成。
- 包含XAML及CodeBehind。
- 优点:
- 上手简单。
- 可以在CodeBehind直接访问UI元素。
- 开发速度很快。
- 缺点:
- 不能使用ControlTemplate进行定制。
- 通常很难继承及扩展。
- 使用场景:
- 需要快速实现一个只有简单功能的控件,而且无需扩展性。
- 不需要可以改变UI。
- 不需要在不同项目中共享控件。
- 使用UserControl的控件:
- Page及DropShadowPanel都是UserControl。
1.2 使用CustomControl自定义控件
- 继承自Control或其派生类。
- 代码和XAML分离,可以没有XAML。
- 可以使用ControlTemplate。
- 控件库中的控件通常都是CustomControl。
- 优点:
- 更加灵活,容易扩展。
- UI和代码分离。
- 缺点:
- 较高的上手难度。
- 使用场景:
- 需要一个可以扩展功能的灵活的控件。
- 需要定制UI。
- 需要在不同的项目中使用。
- 使用CustomControl的控件:
- 控件库中提供的元素,除了直接继承自FrameworkElement的Panel、Shape、TextBlock等少数元素,其它大部分都是CustomControl。
2. 实践:使用UserControl实现DateTimeSelector
上一篇的DateTimeSelector例子很适合讨这个问题。这个控件没有复杂的逻辑,用UserControl的方式实现很简单,代码如下:
public sealed partial class DateTimeSelector3 : UserControl{ /// <summary> /// 标识 DateTime 依赖属性。 /// </summary> public static readonly DependencyProperty DateTimeProperty = DependencyProperty.Register("DateTime", typeof(DateTime?), typeof(DateTimeSelector3), new PropertyMetadata(null, OnDateTimeChanged)); private static void OnDateTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { DateTimeSelector3 target = obj as DateTimeSelector3; DateTime? oldValue = (DateTime?)args.OldValue; DateTime? newValue = (DateTime?)args.NewValue; if (oldValue != newValue) target.OnDateTimeChanged(oldValue, newValue); } public DateTimeSelector3() { this.InitializeComponent(); DateTime = System.DateTime.Now; TimeElement.TimeChanged += OnTimeChanged; DateElement.DateChanged += OnDateChanged; } /// <summary> /// 获取或设置DateTime的值 /// </summary> public DateTime? DateTime { get { return (DateTime?)GetValue(DateTimeProperty); } set { SetValue(DateTimeProperty, value); } } private bool _isUpdatingDateTime; private void OnDateTimeChanged(DateTime? oldValue, DateTime? newValue) { _isUpdatingDateTime = true; try { if (DateElement != null && DateTime != null) DateElement.Date = DateTime.Value; if (TimeElement != null && DateTime != null) TimeElement.Time = DateTime.Value.TimeOfDay; } finally { _isUpdatingDateTime = false; } } private void OnDateChanged(object sender, DatePickerValueChangedEventArgs e) { UpdateDateTime(); } private void OnTimeChanged(object sender, TimePickerValueChangedEventArgs e) { UpdateDateTime(); } private void UpdateDateTime() { if (_isUpdatingDateTime) return; DateTime = DateElement.Date.Date.Add(TimeElement.Time); }}
XAML:
<StackPanel> <DatePicker x:Name="DateElement" /> <TimePicker x:Name="TimeElement" Margin="0,5,0,0" /></StackPanel>
代码真的很简单,不需要GetTemplateChild,不需要DefaultStyleKey,不需要Blend,熟练的话大概5分钟就能写好一个。
使用UserControl有这些好处:
- 快速。
- 可以直接查看设计视图,不需要用Blend。
- 可以直接访问XAML中的元素。
当然坏处也不少:
- 不可以通过ControlTemplate修改UI。
- 难以继承并修改。
- UI和代码高度耦合。
如果控件只是内部使用,不是放在类库中向第三者公开,也没有修改的必要,使用UserControl也是合适的,毕竟它符合80/20原则:使用20%的时间完成了80%的功能。
3. 混合方案
如果需要快速实现控件,又需要适当的扩展能力,可以实现一个继承UserControl的基类,再通过UserControl的方式派生这个基类。
public class DateTimeSelectorBase : UserControl
创建一个名为DateTimeSelectorBase的类,继承自UserControl,其它代码基本上照抄上一篇文章中的DatetimeSelector2,只不过删除了构造函数中的代码,因为不需要DefaultStyle。
然后用普通的方式新建一个UserControl,在XAML和CodeBehind中将基类改成DateTimeSelectorBase,如下所示:
<local:DateTimeSelectorBase x:Class="TemplatedControlSample.DateTimeSelector4" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:TemplatedControlSample" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Name="DateTimeSelector" d:DesignHeight="300" d:DesignWidth="400"> <local:DateTimeSelectorBase.Resources> <local:DateTimeOffsetConverter x:Key="DateTimeOffsetConverter" /> <local:TimeSpanConverter x:Key="TimeSpanConverter" /> </local:DateTimeSelectorBase.Resources> <StackPanel> <DatePicker Margin="0,0,0,5" Date="{Binding Date,ElementName=DateTimeSelector,Mode=TwoWay,Converter={StaticResource DateTimeOffsetConverter}}" /> <TimePicker Time="{Binding Time,ElementName=DateTimeSelector,Mode=TwoWay}" /> </StackPanel></local:DateTimeSelectorBase>
public sealed partial class DateTimeSelector4 : DateTimeSelectorBase{ public DateTimeSelector4() { this.InitializeComponent(); }}
这样既可以在不同的派生类使用不同的UI,也可以使用设计视图,结合了UserControl和TemplatedControl的优点。缺点是不可以使用ControlTemplate,而且不清楚这个控件的开发者会直观地以为这是TemplatedControl,使用上会造成一些混乱。
- [UWP]了解模板化控件(5.2):UserControl vs. TemplatedControl
- [UWP]了解模板化控件(5.1):TemplatePart vs. VisualState
- [UWP]了解模板化控件(5):VisualState
- [UWP]了解模板化控件(4):TemplatePart
- UWP入门(五)--控件模板
- [WPF] UserControl vs CustomControl
- [WPF] UserControl vs CustomControl
- WPF之路——用户控件对比自定义控件(UserControl VS CustomControl)
- 用户控件 UserControl类
- UserControl 用户自定义控件
- 【一分钟了解UWP】微信UWP
- 【一分钟了解UWP】微信UWP
- [UWP控件备忘录]ListView
- win10 uwp 拖动控件
- 动态添加用户控件(usercontrol)
- 用户控件(UserControl) 使用事件
- C# 自定义控件闪烁 UserControl
- win10 uwp 列表模板选择器
- 1003. 我要通过!(20)
- 【剑指offer】数组中只出现一次的数字
- hdu3294_Girls' research_Manacher(马拉车算法)
- python之lxml快速上手_ElementTree(三)
- vb.net 教程 5-15 图像处理之内存处理2
- [UWP]了解模板化控件(5.2):UserControl vs. TemplatedControl
- java(Web)中相对路径,绝对路径问题总结
- linux基础3.4SMTP邮件配置
- poj3348 Cow
- 浅谈面向对象
- NYOJ-248-BUYING FEED(第三届河南省程序设计大赛E题(贪心))
- [UWP]了解模板化控件(5.1):TemplatePart vs. VisualState
- vscode安装设置go
- [UWP]了解模板化控件(5):VisualState