私活后的 WPF 设计经验总结

简介:

WPF 是一个界面层框架技术,要对 WPF 技术达到熟练运用的程度,需要同时拥有开发和设计两方面的知识。而我作为一名开发人员,以前的总结都是站在开发人员的角度,今天这篇博文则期望更多地站在设计人员的角度来进行总结。其实,开发人员比较难理解WPF 框架中为什么会提出 Style、Template、Command、State、StoryBoard、Trigger 等这些概念,但是当你看一看 Flash 或者 PhotoShop 的设计人员平时的工作,就会发现原来许多概念早已是他们的常识,而 .NET 只是把这些概念在 WPF 框架上加以实现而已。

最近接了一个 WPF 的活,对方要求我按照他们美工所画的图,使用 WPF 技术构建一模一样的用户界面。目前项目已经结束,也收到了约定的劳务费用。由于做得还不错,所以他们又和我约定了两个更复杂的项目。其实我个人的 WPF 技术并不高,所以接这个活的一部分原因还是期望通过设计实际的 WPF 项目,来锻炼自己的 WPF 技术。而本篇博文和之前的 WPF 总结不同,主要是想简洁地总结一下项目中的 WPF 实战经验。也就是说,一是只涉及这个项目中用到的概念,而不是所有 WPF 中的概念;二是不会把某个概念技术说透,只从设计人员的角度去讲使用方法。

 

Template


模板是一个可视化控件结构定义,也就是最终界面显示的可视树中控件结构。主要分为两个,一个是 DataTemplate,一个是 ControlTemplate。

DataTemplate 用于为某一类数据定义可视化控件结构。而 ControlTemplate 则是为某一种类型的逻辑控件定义可视化控件结构。一般情况下,使用 ControlTemplate 的场景要远远多过 DataTemplate。

那么如何设计一个 ControlTemplate 中的控件结构呢?其实分两步,第一步,设计这个控件的静态结构;第二步,设计控件的动态行为。其实都很简单,使用 Microsoft Expression Blend 这个专业的 WPF/Silverlight 设计工具进行界面设计,拖拖拽拽就搞定了。

这里要注意的是可视树中的动态行为。主要有两种,一种是模板内部根据各可视控件状态变化而变化的属性设置,可以直接编写在 ControlTemplate 的 Triggers 中,Blend 中则可以直接在 Trigger 面板中进行设计;而另一种行为则需要通过与外层逻辑控件的交互完成。交互的方式有:直接绑定逻辑控件属性、路由命令、路由事件、PART_设计约定。

后三种方式是必须要编写代码才能完成的行为。虽然它们并不是设计人员的工作,但是它们是连接开发与设计的桥梁,鉴于它们的重要性,这里还是专门说明一下:

  1. 路由事件
    在设计自定义逻辑控件时,可以在类型的静态构造器中使用 EventManager.RegisterClassHandler 来处理内部可视树中所有元素的路由事件。举个简单的例子:在 Button 类型的设计代码中,为 LeftMouseButtonDown 事件注册了处理函数,并转换为自己的 Click 事件,这样,点击 Button 内部所有可视控件时,才会触发 Button 的 Click 事件。
    这是一种逻辑控件主动去处理或转换可视控件行为的方式。
  2. 路由命令
    我认为这是一种可视控件主动挑选命令,而逻辑控件被动执行命令调用的方式。
    机制是这样的:控件开发人员为逻辑控件设计了相应的一些行为,但是他们并不知道设计人员会在可视树中用哪一个具体的元素来执行这个行为。这时,开发人员为逻辑控件编写一个路由命令,并在类型静态构造器中为该命令注册处理函数执行相应的控件逻辑。设计人员则只需要在设计控件模板时,为具体元素设置 Command 即可。这样,由于命令也是通过路由事件来进行路由的,所以内部的可视树控件执行命令时,会一直路由到上层的逻辑控件上,并被相应的逻辑处理。达到可视树控件与逻辑控件交互的效果。
  3. PART_ 逻辑控件设计约定
    当开发一个自定义控件时,如果知道这个控件对应的模板中,必须要有一个某一类型控件,这时我们就可以要求模板设计人员必须在模板中添加该类型的控件,并以一个固定的名称命名。这样,开发人员就能在逻辑控件的 ApplyTemplate 方法中通过 Template.Find 找到对应的控件,然后就可以对它进行事件监听、属性控制等操作。而连接逻辑控件、模板中可视树控件的那个名字,为了和一般的命名区分开并显示其重要性,需要使用“PART_” 起头。
    例如,ComboBox 就在类型设计时,指定了至少需要以下两个控件,才能发生正常的下拉行为:

    image

 

Style


样式本质上是对控件的一组属性设置集合。

当我们设计好一个 Style 后,可以把它应用到对应控件的许多实例上,那么就算是通过 Style 默认设置好了这些属性。另外,Style 还提供了 Trigger,可以实现简单地属性变更时设置其它属性的功能。一般较少使用到 EventTrigger。

Style 中我们常常看到的最长的一个属性设置就是设置 Template 属性,即控件的模板。虽然他们俩往往出现在一起,但是 Style 跟 Template 其实没有直接的关系,Style 所做的只是简单地设置一下控件的 Template 属性值而已。

 

有些朋友会问:要达到同样一个效果,我们也可以在 Template 中直接设置视觉控件的属性,例如直接设置边框宽度。那么,为什么还要把一些属性设置编写在 Style 中,再去让 Template 中的控件进行模板绑定,这不是太绕了吗?其实,这样做的好处是使得模板中视觉控件的属性值不会被写成固定值,可以随着外层逻辑控件属性值的变化而变化。这样,当我们直接给逻辑控件设置边框宽度时(本地值),模板中的可视控件就会使用这个更高优先级的值来显示边框。

 

自定义控件


在开发实际项目时,一般都会遇到要开发自定义控件的情况。相关内容上面已经都谈到了,其实挺简单的:

  1. 想好逻辑控件要提供的功能。
  2. 思考这些功能需要为模板设计人员提供哪些接口,一般是:依赖属性、路由命令、PART_ 控件约定。(参考上面的 Template 设计。)
  3. 交互机制确定后,就可以编写相应的后台逻辑控制代码 以及 默认的控件样式(含模板)。

 

其它 Tips 及小技巧


  1. Blend 设计界面固然快,但是每次都需要编译、运行,要看一个效果往往需要多次调整。这时,我们可以使用 snoop 工具来直接调整运行时软件,当效果达到要求时,再把这些满意的值调整到 Blend 中。
  2. 一定要使用 Blend 而不是 VS 来设计界面,除非你对界面没有一点要求。
  3. 忘记“我用 VS 也能设计 WPF 界面”这种不切实际的想法吧。我个人就是因为之前有这种想法,导致一直对 WPF 不开窍。我认为这是一个学习 WPF 的误区,老是以开发人员的思维去思考 WPF。
  4. 学习 Blend 其实是很简单的一件事,相比 VS 的学习成本就简单太多了。如果你要是玩过 Flash、PS,玩起 Blend 来会更快。
  5. 虽然 Blend 说是给设计人员用的,但是我认为只有开发人员才能真正地用好 Blend,用好 WPF。
  6. 对于 XAML,不要象 C# 代码一样的追求代码重用。这种东西,Copy 一下改改就可以了。
  7. Theme 和 Resource:Theme 是主题文件,随着操作系统的主题变化。在开发自定义控件时会自动生成一个 Theme/Generic.xaml 文件。 可以在 Theme/ 这个文件夹中为不同的操作系统主题设计不同的控件样式,而找不到相关主题对应的文件时,则会使用 Generic.xaml 文件中的控件样式。所以:除了自定义控件的样式需要放到 Theme 中,当某个资源要随着系统主题变化而变化时,也需要把它编写到 Theme 文件夹中,否则,应该放到单独的资源文件中并收入到 Application 中。(这一点是个人的理解,不知道对不对,希望懂的大牛给指点下。)
目录
相关文章
|
C# 前端开发
WPF - 图形设计器(Diagram Designer)
原文:WPF - 图形设计器(Diagram Designer)   OpenExpressApp计划中包括建模工具,计划是采用MetaEdit+模型来作为元模型,使用codeproject的《WPF Diagram Designer》一系列文章来做为设计器实现参考,本篇介绍一下codeprojcet的这四个文章,推荐给对图形设计器感兴趣的人去看看,通过WPF的模板功能和其他功能可以很方便的设计出图形编辑器。
3569 0
|
C#
WPF设计の画刷(Brush)
原文:WPF设计の画刷(Brush)   一、什么是画刷         画刷是是一种渲染方式,用于填充图形形状,如矩形、椭圆、扇形、多边形和封闭路径。在GDI+中,画刷分为以下几种:SolidBrush,TextureBrush,HatchBrush,LinearGradientBrush和PathGradientBrush。
1089 0
|
C# Windows
WPF设计の不规则窗体
原文:WPF设计の不规则窗体   我们在工作中,经常会需要画一些不规则的窗体,现在总结如下。 一、利用VisualBrush实现。这依赖于VisualBrush的特性,任何控件可以作为画刷,而画刷又可以作为背景。
965 0
|
C#
WPF设计の自定义窗体
原文:WPF设计の自定义窗体   效果图如下:     实现思路:  1.继承Window类 2.为自定义的CustomWindow类设计窗体样式(使用Blend很方便!) 3.为窗体增加最大最小化和关闭按钮,并实现鼠标拖拽改变窗体大小(使用Derek Bartram的WindowResizer.
1049 0
|
C#
wpf控件设计时支持(2)
原文:wpf控件设计时支持(2) 这篇介绍在wpf设计时集合项属性添加项的定义和自定义控件右键菜单的方法 集合项属性设计时支持   1.为集合属性设计器识别具体项类型 wpf设计器允许定义集合项的类型,如新发布的WPF的DataGrid控件,其中的Columns包括一下几种类型,Columns集合属性是以下几个类型的抽象类集合.
1128 0
|
C# .NET 开发框架
wpf控件设计时支持(1)
原文:wpf控件设计时支持(1)    这部分内容几乎是大家忽略的内容,我想还是来介绍一下. 本篇源码下载 1.属性元数据 在vs IDE中,在asp.net,winfrom等开发环境下,右侧的PropertyGrid属性面板,会对属性进行分类,这有利于了解控件属性的用途.
1027 0
|
C# 容器 数据可视化
wpf控件设计时支持(3)
原文:wpf控件设计时支持(3)     wpf设计时调试 编辑模型 装饰器 1.wpf设计时调试   为了更好的了解wpf设计时框架,那么调试则非常重要,通过以下配置可以调试控件的设计时代码 (1)将启动项目配置成外部的visual studio ide启动程序devenv.
1109 0
|
数据可视化 C# 容器
WPF 多线程 UI:设计一个异步加载 UI 的容器
原文 WPF 多线程 UI:设计一个异步加载 UI 的容器 对于 WPF 程序,如果你有某一个 UI 控件非常复杂,很有可能会卡住主 UI,给用户软件很卡的感受。但如果此时能有一个加载动画,那么就不会感受到那么卡顿了。
1676 0
|
C#
使用Blend设计出符合效果的WPF界面
原文:使用Blend设计出符合效果的WPF界面 之前不会用blend,感觉好难的,但美工给出的效果自己有没办法实现,所以研究了一下blend,感觉没有想象中的那么难 废话不多说,开始界面设计 今天拿到美工给的一个界面效果图 这个界面说实话,还可以吧,勉强说得过去。
2263 0
|
C#
在WPF设计工具Blend2中制作立方体图片效果
原文:在WPF设计工具Blend2中制作立方体图片效果 --------------------------------------------------------------------------------引用时请保留以下信息:大可山 [MSN:a3news(AT)hotmail.
1063 0