本文内容基于微软 Visual Studio 2005 发布前的预览版,之前代号为“Whidbey”。其中所有信息在正式版中都可能会有所改变。
本文所讨论内容:
关于Windows窗体控件的新内容
运用‘主题’
绑定和显示数据
其他数据细节特征
本文使用以下技术:C# 与 Windows 窗体
微软的 .net 框架 1.0 版确实很好地满足了我们的要求。.NET在以下两方面有重要的意义,它不仅根本性地改变了开发者构建与发布 Windows 应用程序的方法,而且还创建了一个巨大的具有很好伸缩特性的技术平台,Visual Studio2005 就是一个很好的例子,它在用户的可定制性和改进的功能性方面都表现的很好。这些变化影响的范围主要集中在 Microsoft .NET框架中的 Windows 窗体子集,从核心的 System.Windows.Forms 命名空间扩展到多种多样的支持性技术,既有旧的也有新的,包括ADO.NET,ObjectSpaces 以及 ClickOnce 部署。
在 Visual Studio 2005 的各个方面都能发现生产效率的提高,包括增强的集成开发环境,改进的控件和数据设计器,还有代码生成器。由于不必手工编写各种各样预定格式的代码,代码编写狂们可能会感到沮丧,而我们就可以有更多的时间来享受我们的生活了。
System.Windows.Forms一些重要的工作已经在 System.Windows.Forms 中做好了,激动人心的新技术中便包含了 Windows 窗体。就在我写本文的同时,可用的命名空间数量和公用类型与成员的组成分别增加了67% 和 127%,这无疑标志着 Visual Studio 2005 是一个卓越的产品。当然本文中我们没有足够的篇幅来讲述每一件事, Figure 1 向我们展示了主要改进方面的概览,这些新增与加强的改进覆盖面较广,例如更好的主题支持,改进的数据绑定,以及 GridView 控件。
类别
描述
布局控件
SplitContainer, FlowLayout, and TableLayout container
用于在设计时和运行时管理控件的控件.
数据绑定控件
GridView 控件用来丰富表格样式数据的表现形式, 查询方式, 与处理方式。 DataContainer用来简化数据绑定和数据绑定用户界面的设计,支持VCR样式的用户界面设计和master-detail 用户界面设计。
用户界面构造组件
MainMenu组件现在支持给菜单项添加图片。WinBar控件提供了与Microsoft Office一样的工具条。WebBrowser控件是一个封装了shdocvw.dll的托管浏览器。
控件与组件
ControlArray使提供单一的接口得到恢复
管理
用来管理许多控件,它们可以使不同的类型。ComponentArray 是代替ControlArray的不错方法,它面向组件。
异步调用支持
后台工作的组件覆盖了工作线程的创建与管理(技术上不从System.Windows.Forms中实现,但确实Windows窗体可以实现).声音文件在声音组件中加载。图像文件在图片框控件中加载。
基本改进
对文本框和复合列表框控件自动完成功能的支持,可自动完成包括IE浏览历史纪录和开始|运行命令等许多系统资源。复合列表框与列表框控件新增了对最进使用过的列表项进行格式化的支持。
Figure 1 新的 Windows 窗体特性
Windows 主题支持当像以往一样创建一个新的Windows窗体工程后,你会发现一个新的变化:默认的Windows主题支持。一个Windows主题就是一组个性化的用户设定,它展示了Windows用户界面的外观。你可以通过在桌面上单击鼠标右键并在弹出的“显示属性对话框”中选择“属性”|“主题”属性页来指定桌面主题。
因为Windows主题是由用户指定的,所以Windows窗体承担了表现它的责任。虽然现有版本的.NET框架支持Windows主题,但是1.0版本需要开发者在文件系统的指定位置添加一个拥有特殊名字的文件来实现。而1.1版通过提供Application.EnableVisualStyles方法并将每个控件的FlatStyle属性值设为"System"来支持Windows主题,从而简化了1.0版的实现过程。 Visual Studio 2005 将会进一步改进此过程,在建立新的Windows窗体工程时默认调用EnableVisualStyles 方法使窗体默认支持Windows主题:
public class Form1 : System.Windows.Forms.Form {
...
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.Run(new Form1());
}
...
}
在以前,将控件的FlatStyle属性值设为"System"就意味着操作系统决定了控件显示时的外观。现在,当FlatStyle属性设置为默认值"Standard"时, Visual Studio 2005的大部分控件都会依据当前正在使用的Windows主题来呈现自己。这与先通过系统设定然后保存你在设计器中的设定结果基本上是一样的。无论FlatStyle 属性为"Standard"还是"System",窗体在运行时会依据主题的改变动态地作出反应,却不需要编写一行代码,这种关于主题的灵敏性对开发者是有利的。
控制布局与配置支持 Windows 主题只需要创建一个工程或窗体,并放入需要的控件。然而,对窗体上的控件进行布局,并对其进行配置是件耗时的工作,尤其是那些复杂的窗体。为了简便,Windows窗体设计器加入了一些新特性,目的就是减少这些琐碎事情所消耗的设计时间。这些特性包括吸附对齐、编辑属性模式以及智能标记,这些特性使操作控件更加容易。你仍旧可以使用Visual Studio的布局工具条来水平或垂直对齐控件,你只需对窗体上的那些控件操纵一次。除此之外,你可以使用吸附对齐来达到与拖拽控件一样的效果,同时避免了在使用布局工具条时选择控件和工具条按钮所带来的设计时间的浪费。吸附式对齐表现为一条或多条有粘性的蓝色线条,控件在这些线条的导引下与邻近的控件对齐。
Figure 2 编辑属性
另一个新特性, 编辑属性模式, 允许你用Tab键遍历控件并在页面上直接改变它们的属性。首先在Windows窗体设计器的上下文菜单中点击选择与其同名的菜单项使编辑属性模式被激活。下一步就是遍历控件并按照你的要求修改属性。过程如Figure 2所示。编辑完成后,点击“返回布局模式”回到正常的编辑模式。设置属性是一个改变控件的简便方法。用另外一个更合适的控件来完全替换当前控件可不容易,你需要删除这个控件,然后将一个新控件拖入窗体并重新配置它。应付像这样复杂的多步设计任务,智能标记正好派上用场,它将设计时的多步任务合并为一步,并在相关控件附近显示菜单项图标作为其标记,智能标记也可以处理简单的设计时任务,这经常会发生,例如在将一个文本框拖放入一个窗体时改变它的"Text"属性。
控件与数据绑定集成开发环境的另一项改进是Visual Studio 2005中的Windows窗体提供了新的控件,并改进了广受欢迎的旧控件例如文本框和复合列表框。Figure 3显示了一个用新增控件和使用中的改进控件创建的小型浏览器,创建他们所需要的代码比在Windows窗体的上个版本中要少。
Figure 3 使用新控件的Web浏览器
这个简单的例子展示了怎样用Visual Studio 2005中增强的工具箱创建丰富的程序,同时减少了代码的编写。例如,设计这个功能齐全的小型浏览器仅仅花了大约10分钟,并且只编写了85行代码来实现传统的全部网页浏览事件,它还实现了URL访问历史记录功能。网页导航和HTML呈现的实际工作是由右侧块形容器中的WebBrowser控件完成的。分割条和左右块形容器都是由一个SplitContainer控件提供的。
Figure 3 中显示的复合列表框展示了新型的自动完成支持功能。自动完成功能通过3个属性来实现,首先是AutoCompleteMode,它可以让你选择样式枚举值来设置自动完成样式: enum AutoCompleteMode {
None = 0x0, // No autocompletion
AutoSuggest = 0x1, // Possible matches chosen from drop-down list
AutoAppend = 0x2, // Possible matches
// appended to text
// while typing
AutoSuggestAppend = 0x3 // AutoSuggest and
// AutoAppend combined
}
除了选择"None",其他选项都需要你设置AutoCompleteSource属性,其值为系统预先设定好的AutoCompleteSource枚举值 :
enum AutoCompleteSource {
FileSystem = 0x1, // File system
HistoryList = 0x2, // All URLs from History list
RecentlyUsedList = 0x4, // All URLs from Recently Used list
AllURL = 0x6, // HistoryList + RecentlyUsedList
AllSystemSources = 0x7, // FileSystem + AllURL
CustomSource = 0x40, // AutoCompleteCustomSource
None = 0x80 // No source
}
设定自定义源的复合列表框需要我们提供自动完成选项,这些选项可以来自存储在AutoCompleteCustomSource属性中的元素的集合。目前,复合列表框和文本框是仅有的提供自动完成功能的控件。
GridView工具箱中的大多数控件都支持数据绑定,通过底层的数据绑定构件来绑定各种各样的数据源。在目前许多情形下,尤其是原型和快速开发中,数据绑定都是关键。Windows窗体开发小组用改进的类型化数据集明显地加强了数据绑定命名空间,包括GridView和DataContainer,并为快速开发加强了设计时支持。这些特性让你开发分区域样式的用户界面或表格样式的用户界面时感到一样的轻松。
有时表格样式的用户界面更适合展现绑定的数据,并且另一方面,微软在其前一个版本的.NET框架中包含了DataGrid控件。对于Visual Studio 2005来说,Windows窗体开发小组响应了社区中关于DataGrid的反馈并决定构造一个新的表格控件,System.Windows.Forms.GridView (参见 Figure 4)。
Figure 4 GridView 列
也许DataGrid与GridView(表格视图)最明显的区别就是GridView的对象模型,它已经被抽象为一个基于列、行的自然表格结构,允许开发者通过大量直观的定位函数来操纵每一个单元格,包括以下几点:
通过样式、格式、布局和选择项支持丰富的自定义用户界面
与DataGrid相比具有显示更多种类数据的能力,新增了一组更加丰富类型,包括图像。诸如冻结列(与Excel中的相似)这样的精彩特性和运行时列的重新排序(与Outlook中的相似)。
构成它的子控件在导航、编辑、验证、自绘和错误处理等方面拥有有超过100个事件
结合过去广泛的设计经验,这些新特性使我们可以快速自定义控件而不用写很多代码,其实是将对DataGrid的特定编码塞进了GridView的方法、属性和事件中。其中的一个例子就是在DataGrid中通过单击单元格来选择一行, 而现在以GridView的SelectionMode 属性的方式暴露出来。当然没有一个控件是十全十美的,当它们表现出不足时,开发者应该依靠其扩展特性来组合出具有自定义特性的控件。GridView控件的底层实现都是基于多种单元格、行和列的,你可以继承并进行扩展。总的来说,GridView作为表格样式的控件比DataGrid更加引人注目。
类型化的数据集GridView 控件是可以绑定数组、集合和类型化数据集的控件家族中的一员。类型化数据集的优点是:.NET框架允许控件在设计器中进行绑定以帮助开发者看到设计好的用户界面。GridView通过在设计时自动生成数据源中每一个字段的数据来实现这项功能。Visual Studio 2005增强了类型化数据集从而使我们的生活更轻松。你将减少花在设计窗体上的时间,类型化数据集现在可以将数据源中的元数据完整的呈现出来,包括外键约束和递增种子以及步骤控制。如Figure 5所示。
Figure 5 默认的类型化数据集
设计器同时也产生一个填充查询,它封装了查询相关表的Select语句并且在类型化数据集中以同名方法实现。有时,系统初始指定的Select、Insert、Update和Delete语句不好用。例如,填充方法将返回所有的雇员信息,而很多时候你只是需要返回一名员工的信息。在这种情况下,使用自己指定的查询语句并填充才是明智之举。类型化数据集设计器允许你添加自己的查询语句,通过在适当表格的上下文菜单中选择“添加”|“查询”来实现。
“数据表查询向导”对话框可以帮助你构造你自己的查询语句,之后数据表会被新数据更新。当你完成类型化数据集的配置后,你会将他绑定到用户界面中的一个或多个控件中。在Visual Studio 2005中, 类型化数据集可以被直接绑定到那些实现了数据源和数据成员属性的控件中,而不必添加数据集对象到窗体中。
DefaultInstance任何曾经大量使用类型化数据集的人都知道,一般来说每一个新的类型化数据集类仅在应用程序的一个地方被使用。因为Windows窗体开发小组了解我们并希望使我们更轻松,他们已经在每个通用的类型化数据集类中设置了一个静态属性DefaultInstance,通过调用它来获取这个单一实例。如下实现:
public static EmployeeTDS DefaultInstance {
get {
if (_defaultInstance == null) {
_defaultInstance = new Northwind();
}
return _defaultInstance;
}
}
你可以这样使用DefaultInstance属性:
public class Form1 : System.Windows.Forms.Form {
...
private void Form1_Load(
object sender, System.EventArgs e) {
// Load data
EmployeeTDS.DefaultInstance.LoadData();
}
...
}
数据绑定控件使用DefaultInstance的类型名设置它们的数据源属性,类型名默认为"工程命名空间 。类型数据集名"的形式,而随后指定数据成员的步骤保持不变。
DataContainer控件GidView 控件是复杂绑定控件的一个例子,它意味着控件知道怎样管理数据绑定以支持查询、插入、更新和删除操作。相反,简单数据绑定控件不知道这些,需要你通过数据源绑定管理器来实现与复杂绑定控件相同的功能,特别是带有那种VCR样式控件的用户界面。当你偏爱列表样式的数据而不是表格式的数据时,你可以使用简单数据绑定控件。这种方法需要你手动将一系列适当的控件分区域地添加到窗体中,例如标签和文本框,结果就像Figure 6显示的那样。
Figure 6 基本用户界面
当你可以手动实现如此细致的窗体时,在Visual Studio 2005 中你也可以通过DataContainer绑定一个类型化数据集一次性实现这个窗体。仅需要简单地从DataContainer的智能标签中选择名称为这个窗体的菜单项。
这一特性会依据选择的数据源为你自动生成所有的控件区域。而且,DataContainer将会加载并保存这些数据,还会默认地添加VCR样式的导航与编辑控件而不用编写代码。结果如Figure 7所示。
Figure 7 带有VCR控件的分区域样式的用户界面
如果你的界面需求改变了而且你发现表格样式的用户界面更合适,你可以用DataContainer来完成如此艰巨的任务,你只需要从DataContainer 中选择适当的智能标记选项。设计器便删除所有现存的控件,代之以一个DataGrid(在未来版本的Visual Studio中也许会是一个GridView)。
Master-detail绑定多功能的DataContainer也是构建master-detail用户界面的强大工具,这种界面提供了一种基于窗体的可视化效果,来展示关系数据库中经常用到的一对多关系。例如显示雇员--订单关系,我们只需要简单地将订单表添加到类型化数据集中就可以正确配置。
Figure 8 Master-detail窗体
既然我们已经生成了master用户界面(如Figure 7所示),我们接下来所要做的就是将一个GridView拖拽到窗体上,并将其数据源属性设为DataContainer,数据成员属性设为订单--订单明细关系(这里为订单--雇员外键约束),结果如 Figure 8。
ClickOnce 部署当你在窗体中设置好了所有的控件,并编写了使它们共同工作的代码,你将要部署此应用程序。为大量的用户们部署一个企业级的Windows窗体应用程序将会面临一个关于安装与版本变更的严峻挑战,所以上一辈的开发者更愿意舍弃丰富的Windows用户界面而转向Web应用程序并享受其所带来的部署的便利性。
在.NET中,微软开始创建一个底层结构,它使得发布Windows窗体应用程序与发布ASP.NET应用程序一样轻松。在Visual Studio 2005之前, .NET框架支持no-touch部署, 其允许Windows窗体应用程序从一个URL或一个统一名称转换(UNC)文件路径进行部署,并在客户机中的一个沙箱中运行,这个沙箱具有代码访问安全(CAS)性。在Visual Studio 2005中No-touch部署进化到了ClickOnce部署,并出现了一些新的特性给Windows窗体程序开发者提供了一个像部署Web应用程序一样平滑的底层结构。 特别地,ClickOnce部署还提供了对一些经过改进的功能的支持,如程序发送、版本更新与回滚、对客户端应用程序安装的更多控制、更新许可和包含在Visual Studio所有结构中的设计时配置支持。
配置流水线型部署在设计时,通过在Visual Studio2005的工程配置属性中设置发布属性页的各项属性,可以对ClickOnce部署进行配置。依据你的底层结构和用户群,不同的部署资源(文件服务器、Web服务器或者FTP服务器)有其特定的意义。ClickOnce部署允许你指定哪些将要被发布和安装以及安装方式(例如,通过网页进行安装)。可以通过配置来决定应用程序是否被安装到客户机器的物理驱动器上。如果客户端安装完成,你可以规定在程序装载或运行之前是否进行更新检查,或多长时间进行更新检查,或是强迫要求更新--对进行关键性的更新操作来说是个有用的功能。它也可以指定安装程序前的必备条件,.NET框架程序本身就是这样。而且在安全属性页中可以设定一些安全设置。
当将要发布时,你可以通过点击“工程”|“发布工程”菜单一步生成并发布你的应用程序,它既生成了应用程序也发布了应用程序。发布应用程序的过程由发布向导程序进行管理,它主要查看你的发布配置设定,并允许你在发布前更改这些配置。在发布过程中最后弹出的一个窗体列出了所有需要确定的选项,并且提供了一个选项用来确定是发布程序还是返回修改设定。之后发布向导根据你的选择按照要求发布应用程序。
部署程序部署程序开始于用户打开部署Web页面并点击发布此程序所需的超链接。应用程序被链接到一个.Deploy文件而不是一个可以自运行的程序。.deploy文件是ClickOnce部署程序所必须的两个文件之一,它指定了程序部署与更新需求。第二个文件是.manifest文件, 它指定了程序运行所需要的文件。这相当于程序的装配清单。.deploy与.manifest文件都在客户端被ClickOnce部署服务处理,System.DeploymentFramework.Service.exe. 这个服务随.NET框架一同被安装,并且第一此启动时需要一个.deploy文件。它会以对话框的形式要求确认下载,而用户不会看到任何的后台操作。下载完成后,真正的应用程序会被加载到AppHost.exe程序,并由其运行。应用程序会存储在本地的缓存中,直到你指定没有客户端安装操作。以后应用程序启动总需要这个.deploy文件,并且在本地缓存中被执行直到.debug文件指定在服务器端有新的版本。
如果应用程序运行在要求更高可配置安全性的领域(例如互联网或者局域网),ClickOnce部署程序可以为用户提供达到相应级别的程序访问许可证,以确保程序的正确执行。如果没有许可程序永远不会启动,根本就不会给其运行的机会。
ClickOnce 部署的版本控制与回滚如果部署了一个程序,一个图标便会添加在“开始”菜单上并且在控制面板|添加删除程序中新增了一项。从添加删除程序中,你可以完全卸载应用程序或者返回到前一个版本,如果存在前一个版本的话。流水线部署程序的版本控制功能主要依赖于你使用AssemblyVersion属性所指定的版本号,AssemblyVersion属性在AssemblyInfo.cs文件中被生成,AssemblyInfo.cs文件是每一个Windows窗体工程默认生成的。就像这样:
[assembly: AssemblyVersion("1.0.*")]
版本号被用来决定是否有一个新的版本可以用于下载。它也用来命名部署文件夹和程序所在的客户端临时文件夹。两个文件夹的名称转换形式为程序名_主号_辅号_生成号_修订号。
ClickOnce 部署是一项十分强大的技术,它为我们带来了很多好处,在本文中无法一一描述。然而,使用ClickOnce部署的主要动机是为了部署、安装和控制版本的方便。想要了解关于它的更多信息,请参考本期MSDN杂志中由Brian Noyes撰写的名为 "ClickOnce: Deploy and Update Your Smart Client Projects Using a Central Server" 的文章。
总结当你考虑 Visual Studio 2005 中大量的新特性时,你会意识到,我们仅仅刚刚开始讨论这些你会在Windows窗体开发中用到的各种技术。这些包括改进的ADO.NET和新的通过对象--关系映射访问关系数据库的方法,它利用了展新的ObjectSpaces技术。这里所写的内容只向你介绍了一些最重要的新特性,并解释了Visual Studio的易用性所带来的生产效率的提高,从集成开发环境和设计器的改进到以前版本中控件的改进(如文本框和复合列表框)和一些全新的控件(例如GridView和WinBar)。GridView 和 DataContainer控件与增强的类型化数据集一起 ,帮助你创造丰富的数据表现形式和将数据更快地加入到应用程序。最后,ClickOnce部署简化了Windows窗体程序部署的全过程,同时提供了与传统安装程序的兼容性。
作者简介Michael Weinhardt 现在正与 Chris Sells 一起更新他的新书《C# Windows 窗体程序设计》,并为 MSDN 在线杂志撰写专栏文章“Windows 窗体探密”。访问 http://www.mikedub.net 获取更多信息。
Chris Sells 是一位 MSDN 在线杂志的内容策划,目前主要研究代号为“长角”的下一版 Windows 操作系统 (http://msdn.microsoft.com/longhorn )。关于 Chris 和他各项研究成果的更多信息参见 http://www.sellsbrothers.com。
本文出自 MSDN Magazine 的 May 2004 期刊,可通过当地报摊获得,或其最好是 订阅
本文由 VCKBASE MTT团队 翻译