一:首先来看一下UserControl

熟悉XAML的朋友们都知道,当我们创建一个用户控件的时候,VS会自动为我们生成一个XXX.xaml文件和XXX..xaml.cs文件,XAML文件用于进行控件的UI界面设计,对应的CS文件则是进行逻辑代码的编写。我们主要看一下CS文件,打开CS文件,我们会发现我们自己创建的自定义控件继承自UserControl(别忘了对应的XAML中也是以UserControl为根结点),我们可以按下F12键来看一下UserControl:

我们可以明显的看到UserControl继承了一个“Control”类和一个“IUserControl”接口,我们暂时只看“IUserControl”接口。继续F12它,看看它到底是什么东西:

里面很简单,就只有一个Content字段,但不要大意,它可是UIElement类型的哦!:),不明白它是干什么的话,不着急,我们可以看一下” UserControl “中的东西:

这下明白了吧,我们能够在自定义用户控件中直接写控件多亏有了它。这就有点类似于让你创建一个简单的图片按钮。

SDK中是这样描述UserControl的:为定义一个封装相关的现有控件并提供其自身逻辑的新控件提供基类。简单理解就是为新控件定义基类,但这个新控件是有限定的,即是在现有控件的基础上创建的。这表明使用UserControl来创建自定义控件并不是很强大,它只能满足基本的自定义控件的需求。如果你的自定义控件只是几个现有控件的堆砌,样式的简单修改,属性事件的简单注册,它还是能满足你的需求,但是你想更加深入的修改那就没有想象中那么简单,比如你想卸载掉一些你自定义控件不支持但UserControl已经为你注册了的事件,这无疑是画蛇添足了!

这就好比你要盖房子,微软已经为你把最大众的房屋骨架搭建好了。厨房、卧室、客厅什么的都为你设定好位置,你就按照这个来,具体内部怎么装修你自己看着办他不管,但是你想把厨房的位置挪到客厅,客厅的位置挪到卧室,建自己的小别墅,他允许你建,但后果自负,并且工作量也挺大的。哎,不说了,想想都可怕!要是你的房子,你愿意这样折腾吗?

二:其次来看一下TemplatedControl

TemplatedControl是名副其实的自定义控件,它做到了真正的自定义,它要比UserControl更加的灵活。它只为你提供了作为一个控件最基本的属性和方法。所以你现在真是在以“小米加步枪”的装备来进行自定义控件。

当我们创建一个CustomControl的时候,VS会自动为我们创建一个XXX.cs文件和一个位于在Themes文件夹下的Generic.xaml文件。Generic.xaml文件主要是自定义控件的样式编写,但它的编写不同于普通的XAML文件,它是以样式的语法格式来进行编写。

看上面这段代码我们可以明显的注意到这个自定义控件是通过Style的方式来进行编写,TargetType表明我们需要对哪个声明的自定义控件进行样式的编写,ControlTemplate表明我们是要进行控件模板样式的设计,然后Border里面的元素就是你需要进行的样式设置。这个文件中的代码基本上没多大问题,但需要注意的问题是,由于Generic.xaml是一个样式文件,因此VS并不能为你实时展示它的样子。

接下来看一下我们创建的CustomControl.cs文件:

代码很简单,就仅仅一个构造函数,里面加了一句声明该控件默认的样式。我们看一下它的基类:Control,它与用户控件在后台代码方面最明显的一个区别就是它只继承了Control基类,而没有继承IUserControl接口,因此它里面是没办法直接放控件。像下面的这段代码这样写就是错误的:

至于怎么解决不是本文的重点,感兴趣的朋友可以自行百度,我们继续往下说。通过上图我们还发现一个问题,就是XAML设计器已经将我们自己定义的自定义控件看作最小的控件单位,不允许其再嵌套子控件,不管你内部实现多么复杂,在我外部看来就是一个整体。由于我们的自定义控件只继承了Control,所以我们有时候不得不自己定义一些属性、方法和事件,这并不是什么坏事,我们也可以因此更好的进行自定义控件。

SDK中是这样描述Control的:表示UI元素的基类,这些元素可使用ControlTemplate来定义其外观。用于ContentControlUserControlItemsControl和几个实际控件的父级类。这句话就不难理解了吧,它的适用范围要远远大于UserControl。进一步提高了在编写自定义控件的灵活性。

这就好比你要盖房子,微软已经给你准备好了盖房子需要的基本原料,但他没有给你搭建房屋的骨架,除了原料你不用担心,其余什么你都需要自己搞定。至于房子盖成什么样要看你的能力。

三:建议

如果一个Page中的控件较多,各种各样的控件都有,布局也相对麻烦,你会怎么处理页面布局?难道要都写到一个XAML文件中吗?如果代码少还可以接受,但是一不小心写了上千行怎么办?所以这个时候合理使用用户控件和模板控件不失为一种理想的选择。下图是我个人在使用中的布局规则,仅供参考:

三:总结

就像Tony Champion(MVP)说的那样:UserControls are easier to create and maintain.  However, custom controls are more flexible. 既然鱼和熊掌不能兼得,那就要看你的选择。在实际项目中,常常会将几个普通的控件放到一个用户控件中,这样便于维护。但是如果让你 “从无到有”写一个相对复杂的控件,里面的逻辑要远远比普通控件复杂,你依然会选择使用用户控件吗?在我看来,UserControl属于创建方便管理类型的控件,而TemplatedControl才是真正意义上创建自定义控件。UserControl能做到的事情TemplatedControl也能做到,但TemplatedControl能做到的事情UserControl不一定能做到。简而言之:当你有多个简单控件需要多次组合复用,建议使用userControl,当你需要完完全全编写一个自定义控件,建议使用TemplatedControl。

UserControl VS TemplatedControl的更多相关文章

  1. [UWP]了解模板化控件(5.2):UserControl vs. TemplatedControl

    1. UserControl vs. TemplatedControl 在UWP中自定义控件常常会遇到这个问题:使用UserControl还是TemplatedControl来自定义控件. 1.1 使 ...

  2. [UWP 自定义控件]了解模板化控件(5.2):UserControl vs. TemplatedControl

    1. UserControl vs. TemplatedControl 在UWP中自定义控件常常会遇到这个问题:使用UserControl还是TemplatedControl来自定义控件. 1.1 使 ...

  3. [UWP]了解模板化控件(1):基础知识

    1.概述 UWP允许开发者通过两种方式创建自定义的控件:UserControl和TemplatedControl(模板化控件).这个主题主要讲述如何创建和理解模板化控件,目标是能理解模板化控件常见的知 ...

  4. UWP 自定义控件:了解模板化控件 系列文章

    UWP自定义控件的入门文章 [UWP 自定义控件]了解模板化控件(1):基础知识 [UWP 自定义控件]了解模板化控件(2):模仿ContentControl [UWP 自定义控件]了解模板化控件(2 ...

  5. [UWP 自定义控件]了解模板化控件(1):基础知识

    1.概述 UWP允许开发者通过两种方式创建自定义的控件:UserControl和TemplatedControl(模板化控件).这个主题主要讲述如何创建和理解模板化控件,目标是能理解模板化控件常见的知 ...

  6. 一种开发模式:ajax + ashx + UserControl

    一.ajax+ashx模式的缺点     在web开发过程中,为了提高网站的用户体验,或多或少都会用到ajax技术,甚至有的网站全部采用ajax来实现,大量使用ajax在增强用户体验的同时会带来一些负 ...

  7. Wpf usercontrol dispose

    窗口关闭时组件"析构": public UserControl()        {            InitializeComponent();               ...

  8. XAML UserControl的继承

    欢迎访问Heroius博客:崩溃的脑壳查看文章原文! 前言 相信不少学习WPF和Silverlight的同学们都出于Winform的习惯,希望能够在新展示层框架中实现控件的继承.本文就是说明如何实现这 ...

  9. wpf的UserControl用户控件怎么添加到Window窗体中

    转载自 http://www.cnblogs.com/shuang121/archive/2013/01/09/2853591.html 我们来新建一个用户控件UserControl1.xaml &l ...

随机推荐

  1. 通过linux核映射驱动访问GPIO

    1. HPS GPIO原理 1.功能方块图 linux内核是通过Linux内核memory-mapped device驱动访问GPIO控制器的寄存器而控制HPS端用户的LED和KEY的.memory- ...

  2. cf 20C Dijkstra?

    带队列  dijkstra #include <iostream> #include <cstdio> #include <queue> #include < ...

  3. 背水一战 Windows 10 (67) - 控件(控件基类): DependencyObject - CoreDispatcher, 依赖属性的设置与获取, 依赖属性的变化回调

    [源码下载] 背水一战 Windows 10 (67) - 控件(控件基类): DependencyObject - CoreDispatcher, 依赖属性的设置与获取, 依赖属性的变化回调 作者: ...

  4. React-Native 问题随记2: com.android.builder.testing.api.DeviceException

    错误详细: Execution failed for task ':app:installDebug'.> com.android.builder.testing.api.DeviceExcep ...

  5. JS跨域调用之document.domain--相同基础域名页面之间的调用

    利用document.domain 实现跨域: 前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域 Javascript出于对 ...

  6. Android Studio 配置 androidAnnotations框架详细步骤

    第一步:打开app的build.gradle文件 第二步:添加下面红色的部分 apply plugin: 'com.android.application' android { compileSdkV ...

  7. react-router V4中的url参数

    概述 之前写过react在router中传递数据的2种方法,但是有些细节没有理清楚,现在补上,记录下来,供以后开发时参考,相信对其他人也有用. 参考资料:stackoverflow react rou ...

  8. 从app上传图片到php,再上传到java后端服务器的方法一条龙服务

    在现在的网络开发中,上传图片类的需求实在是太普通不过了,但是对于怎么样做到上传图片,对于刚开始建立项目的时候,还是有点不知所措的.也许有幸,我们做的项目是之前已经有人写过类似的用例了,那么我们只需要依 ...

  9. IDEA 图标介绍。 缓存和索引介绍、清理方法和Debug使用

    一.图标 二.缓存和索引 IntelliJ IDEA 的缓存和索引主要是用来加快文件查询,从而加快各种查找.代码提示等操作的速(上图中的图标能这样显示也是靠索引).某些特殊条件下,IntelliJ I ...

  10. HoloLens开发手记-硬件细节 Hardware Detail

    微软HoloLens是世界第一款完全无线缆的全息计算机.通过在新方式上赋予用户的全息体验,HoloLens重新定义了个人计算(Personal Computing).为了将3D全息图形固定到你周围的真 ...