在图形化用户界面编程中,用户控件是一个很重要的概念。本质上我们的图形化用户界面是由各种控件构成,这些控件有些是IDE开发商提供的,有些是第三方提供的,若这些控件都不能完成功能则需要自己编写控件了。在C#中编写一个控件很简单,以下代码就能实现一个用户控件。
在此小弟提出“虚控件”的概念,所谓虚控件就是在控件和操作控件的代码之间放置一个代理层,所有的代码通过这个代理来操作控件,而控件的事件也通过这个代理层来调用相关的控制代码,控件和代码不直接发生关系。以下代码实现了一个简单的“虚控件”中的代理层
设计良好的虚控件的代理层能使得代码的编写和实控件的代码的编写没有多大的区别。
虚控件是不能直接使用的,它得依附在其他控件使用,首先在窗体中放置一个标准控件,比如Panel等等。然后实例化一个虚控件,调用VirtualControlBase.BindControl 属性来进行控件绑定,如此才可使用。
为何开发一个用户控件需要如此多此一举。其实这样做有不少好处,可列举的有
- 有利于代码的分离和模块化
- 实控件只能使用于图形化用户界面程序,而虚控件除了应用于图形化用户界面程序外还可使用于其他任何类型的程序,包括命令行程序,ASP.NET,WebService,Windows服务。这个特性可以适用于某些程序的移植。例如将GUI程序移植到ASP.NET中,GUI程序中编制了虚控件绘制的复杂图形,而后在ASP.NET程序中,它创建一个BMP图片,然后使用库函数System.Drawing.Graphics.FromImage创建一个Graphics对象,然后调用虚控件的HandlePaint来绘制这个复杂图形,然后就可以发布出去了。这样虚控件既可用于GUI程序又可用于ASP.NET程序,实现了代码的重用。利用这个特性还能比较好的修改旧的GUI代码,保持原有功能并向ASP.NET等非GUI程序提供图形支持。
- 虚控件可以减少控件的个数,在某些GUI应用中,窗体中可能堆积很多一样的控件,例如窗体有一个TabControl,有很多页,每页中放一个相同类型的用户控件,用户需要在这些控件来回切换。大家知道.NET的控件是基于Win32的窗体的,创建一个控件比较费力,消耗资源。而虚控件本质上只是一个类,在.NET中创建一个类是很简单的。这样在窗体中只要放置一个控件,然后生成很多虚控件,在各个控件来回切换就转换为各个虚控件绑定和取消绑定实控件的操作。而且在窗体中放置大量的控件不利于窗体设计器的工作。若某个控件在设计状态下发生错误则会影响窗体设计器的正常工作。(在VB中若用户控件加载错误会自动转换为一个PictureBox控件,所有的设计属性都会丢失)
- 使用某个控件前需要在VS.NET的工具箱中加入这个控件的图标,这个操作比较麻烦,而且打开其他不需要该控件的工程中,工具箱还会显示该控件的图标。而使用虚控件则不会出现这种情况
其实虚控件的概念还能用VB来实现,以下代码就是一个简单的例子
以下是C#编写的一个虚控件代理层的完整代码。