如果只是使用现有的WPF控件的话,是很难满足当前社会多复杂的业务。所以用户自己订制一系列控件也是一种不可避免的情势。WPF在控制方面分为俩种:用户控件和自定义控件。相信看过前面章节的就明白他们俩者之间的差别。理解用户控件并不难——把现有的控件组合在一起形成的控件。而在笔者看来自定义控件才是WPF最吸引人的地方。

关于用户控件的话,往往就是一个xaml文件,也可以是一个DLL文件。但是自定义控件往往都是一个DLL文件。引用这个DLL文件时候,应用会去加载dll文件里面的Theme文件夹下的Generic.xaml文件,从而宣染自定义控件。在Generic.xaml文件里面存放了若干个自定义控件的xaml文件。如下。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:FirstFloor.ModernUI.Windows.Controls"
xmlns:shell="http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell"> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Themes/BBCodeBlock.xaml" />
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Themes/ModernButton.xaml" />
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Themes/ModernDialog.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary>

上面是不是有一点类似于App.xaml的内容。当我们引用这个自定义控件DLL文件的时候,就会去加载当前Theme文件夹/Generic.xaml文件。这里有一点要小心——一定要在自定义控件类的构造函数里面指定相关的Style类型。如下。

        public ModernButton()
{
this.DefaultStyleKey = typeof(ModernButton);
}

假设我们编写完若干个自定义控件。那么为了方便引用这些控件。往往我们用到引路径的功能。如下

  xmlns:mui="http://firstfloorsoftware.com/ModernUI"

设置好了引用的路径。页面上就可以如下方式进行使用。

  <mui:ModernButton Content="modern button" IconData="{StaticResource HomeIconData}" Margin="0,0,0,8" />

如果我们不使用引用路径的话,在使用自定义控件的时候,就必须把相关命名空间一并引用进来。类似下面

 xmlns:app="clr-namespace:FirstFloor.ModernUI.App"

那么,如果控件存在不同的命名空间又如何呢?不好意思,请把所有相关的命名空间全部都引进来吧。但是引用路径则不用。为什么呢?看下面就知道了。

[assembly: XmlnsDefinition("http://firstfloorsoftware.com/ModernUI", "FirstFloor.ModernUI.Presentation")]
[assembly: XmlnsDefinition("http://firstfloorsoftware.com/ModernUI", "FirstFloor.ModernUI.Windows")]
[assembly: XmlnsDefinition("http://firstfloorsoftware.com/ModernUI", "FirstFloor.ModernUI.Windows.Controls")]
[assembly: XmlnsDefinition("http://firstfloorsoftware.com/ModernUI", "FirstFloor.ModernUI.Windows.Converters")]
[assembly: XmlnsDefinition("http://firstfloorsoftware.com/ModernUI", "FirstFloor.ModernUI.Windows.Navigation")]
[assembly: XmlnsPrefix("http://firstfloorsoftware.com/ModernUI", "mui")]

这一个部分的代码是在Modern UI for WPF开源项目的FirstFloor.ModernUI项目的AssemblyInfo.cs文件里面。FirstFloor.ModernUI项目就是一个自定义控件的项目。上面的引用路径可以说是一对多的关系。不用笔者讲解了吧。

记得上一章节中讲到每一个用户控件都会实现于FrameworkElement类。在FrameworkElement类中有一个属性叫Template。他是自定义控件的核内点。从字面意义来讲就是模板的意思。笔者是这样子理解的。自定义控件事实上就是控件的显示模板在重新用自己的意思画了一片。如下是笔者在新建自定义控件时候,VS帮忙生成的。笔者略做修改一下。笔者加了一个TextBox。Text为AomiCustomTextBox。

<Style TargetType="{x:Type local:CustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBox Text="AomiCustomTextBox"></TextBox>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

显示结果:

那么,如果Template(ControlTemplate)是用于自定义控件。里面有一个跟他类似的DataTemplate又是用于做什么呢?事实上在开发WPF的时候,我们也会常常用到他们。如果不搞清楚他们之间的作用差别的话,有时候会误事。MSDN上面是这样子定义的。ControlTemplate是用于定置一个控件可视化结构和行为方面。这里要注意的是一个控件。而DataTemplate是定置一个业务对象的可以视化结构。即是面向对象不同。是事实在开发过程有时候也会有这样子的感觉,ControlTemplate一般都是用TemplateBinding来邦定数据,而DataTemplate用的是标准的binding。什么意思呢?也就是说ControlTemplate一般会去找控件自身的依赖属性。而是DataTemplate则是去找DataContext。

那么俩者可不可以同时使用呢?答案是肯定可以的。这个时候就要小心了。往往会出现一些互相影响的事情。但是一定要认清楚一点:ControlTemplate是不管业务数量的展示。他只管控件布局结构。DataTemplate反之。

引用定义控件离不开Theme文件夹下的Generic.xaml文件。那么这里笔者有一个疑问——App.xaml上面的引用和Generic.xaml文件里面的引用又有什么区别呢?WPF所有控件都有一个黙认的样式。这个样式往往是通过控件的DefaultStyleKey依赖属性来确定的。而默认的样式文件名往往会根据当前操作系统的不同而不同。如下

1.Generic.xaml:如果下面的黙认样式都没有情况下会被引用。笔者喜欢叫标准样式。

2.Luna.Xxx.xaml:在XP系统下引用的黙认样式。如:Luna.Homestead.xaml、Luna.Metallic.xaml

3.Aero.Xxx.xaml:在Vista下引用的黙认样式。如:Aero.NormalColor.xaml

所以笔者也很难区分App.xaml和Generic.xaml上面的差别。因为俩者太像了。笔者略微的做了一个实验看一下是App.xaml和Generic.xaml谁先执行。结果是Generic.xaml。所以如果你在App.xaml里面定义一个样式,想在Generic.xaml里面StaticResource引用会报错的。具体的话,笔者觉得各位可以去试一下。值得注意的:往往App.xaml引用的资源文件都是标准控件(颜色,WPF本身的控件)的样式。而Generic.xaml一般用于自定义控件的资源文件。

WPF 杂谈——自定义控件的更多相关文章

  1. WPF 杂谈——开篇简言。

    这俩年多来笔者一直在从事关于WPF的开发.虽然不能说是专家级别的.但是对于WPF的应用还是有一定的了解.论他的灵活性决对不在WinForm之下.WPF的出现更是引发一段热议.他的何去何从更是让很多人感 ...

  2. WPF 杂谈——开篇简言

    这俩年多来笔者一直在从事关于WPF的开发.虽然不能说是专家级别的.但是对于WPF的应用还是有一定的了解.论他的灵活性决对不在WinForm之下.WPF的出现更是引发一段热议.他的何去何从更是让很多人感 ...

  3. 在WPF中自定义控件

    一, 不一定需要自定义控件在使用WPF以前,动辄使用自定义控件几乎成了惯性思维,比如需要一个带图片的按钮,但在WPF中此类任务却不需要如此大费周章,因为控件可以嵌套使用以及可以为控件外观打造一套新的样 ...

  4. 在WPF中自定义控件(3) CustomControl (上)

    原文:在WPF中自定义控件(3) CustomControl (上) 在WPF中自定义控件(3) CustomControl (上)                              周银辉 ...

  5. 在WPF中自定义控件(3) CustomControl (下)

    原文:在WPF中自定义控件(3) CustomControl (下)   在WPF中自定义控件(3) CustomControl (下)                                 ...

  6. 在WPF中自定义控件(1)

    原文:在WPF中自定义控件(1)    在WPF中自定义控件(1):概述                                                   周银辉一, 不一定需要自定 ...

  7. 在WPF中自定义控件(2) UserControl

    原文:在WPF中自定义控件(2) UserControl 在WPF中自定义控件(2) UserControl                                               ...

  8. [转]在WPF中自定义控件 UserControl

    在这里我们将将打造一个UserControl(用户控件)来逐步讲解如何在WPF中自定义控件,并将WPF的一些新特性引入到自定义控件中来.我们制作了一个带语音报时功能的钟表控件, 效果如下: 在VS中右 ...

  9. WPF 杂谈——入门介绍

    对于WPF的技术笔者是又爱又恨.现在WPF的市场并不是很锦气.如果以WPF来吃饭的话,只怕会饿死在街头.同时现在向面WEB开发更是如火冲天.所以如果是新生的话,最好不要以WPF为主.做为选择性来学习一 ...

随机推荐

  1. 手机自动化测试:appium源码分析之bootstrap三

    手机自动化测试:appium源码分析之bootstrap三   研究bootstrap源码,我们可以通过代码的结构,可以看出来appium的扩展思路和实现方式,从中可以添加我们自己要的功能,针对app ...

  2. 性能调优:mysql之left join

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...

  3. python webdriver安装

    前言 本次就python webdriver的安装和驱动不同浏览器的配置进行分享,以解决大家在入门过程中的一些基本的环境问题. python安装 目前python有2.x和3.x版本,笔者在这里推荐2 ...

  4. Python javascript操作DOM

    文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把 ...

  5. 一个只有99行代码的JS流程框架

    张镇圳,腾讯Web前端高级工程师,对内部系统前端建设有多年经验,喜欢钻研捣鼓各种前端组件和框架. 最近一直在想一个问题,如何能让js代码写起来更语义化和更具有可读性. 上周末的时候突发奇想,当代码在运 ...

  6. 初探CSRF在ASP.NET Core中的处理方式

    前言 前几天,有个朋友问我关于AntiForgeryToken问题,由于对这一块的理解也并不深入,所以就去研究了一番,梳理了一下. 在梳理之前,还需要简单了解一下背景知识. AntiForgeryTo ...

  7. php面向对象(一)---2017-04-17

    重点:定义类与实例化类:访问修饰符:构造函数 一.面向对象 面向对于与面向过程的主要区别在于:前者包含类和对象的概念 二.类和对象   1.类是由众多对象抽象(归纳总结)出来的东西  代表所有对象的特 ...

  8. 函数指针|指针函数|C文件操作

    body,table { font-family: 微软雅黑; font-size: 10pt } table { border-collapse: collapse; border: solid g ...

  9. MVC框架中,遇到 [程序集清单定义与程序集引用不匹配]怎么办?

    项目里有一个WinForm程序,它需要使用一套第三方控件.而我的机器上存有这套控件的两种版本(一个是源码版,一个是演示版).结果经常出现“程序集清单定义与程序集引用不匹配的问题”的异常.最要命的是有时 ...

  10. js中的事件委托详解

    概述: 那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.那这是什么意思呢?网上的各位 ...