从事Winform开发框架的研究和推广,也做了有几个年头了,从最初的项目雏形到目前各种重要特性的加入完善,是经过了很多项目的总结归纳和升华,有些则是根据客户需要或者应用前景的需要进行的完善,整个Winform开发框架具有很好的通用性和借鉴性,本文从该Winform开发框架进行概括总结,力求把各个重要的特性进行一些详细的说明,使大家了解整个Winform开发框架的面貌和特性。

Winform开发框架总体性概括有:支持插件化应用开发,能够动态配置及加载开发的插件;菜单支持动态配置,可根据用户权限进行动态控制显示;集成各种独立开发好的模块,如权限管理系统、字典管理模块等,自动更新模块等,实现系统的权限控制、字典管理、软件支持远程自动更新等功能;可重复使用的系统基础模块,Winform分页控件和.NET开发公用类库等;整个框架通过与代码生成工具Database2Sharp进行配合,能够一键生成整体性框架代码,Winform系统界面代码,开发更高效。

整个Winform开发框架,提供了很多常见业务系统提供的功能,包括Excel数据导入导出,能快速导入自定义模块的Excel数据,快速导出列表数据;自定义Excel自定义模板报表的生成,生成各种复杂的Excel报表;强大通用的统计图表模块,数据统计更方便;基于多数据的数据查询模块和通用高级查询模块,查询数据更方便;框架提供基于多种数据库(Sqlserver/Oracle/Mysql/Sqlite/Access)的整合,能够手动配置数据库类型,通用模块内置支持多种数据库切换;框架提供了高度封装的数据访问基类,开发代码更少更高效;框架界面基类也进行统一封装,使用更方便,效果更统一;框架提供基础性的支持,包括集成登陆、闪屏、托盘功能,以及为插件模块提供登陆用户信息和系统信息。

Winform开发框架的主要功能概览如下图所示。

图片 1

1、支持插件化应用开发,能够动态配置及加载开发的插件

框架实现基于插件化的应用,如下所示。

图片 2图片 3

支持插件化应用的开发框架能给程序带来无穷的生命力,也是目前很多系统、程序追求的重要方向之一,插件化的模块,在遵循一定的接口标准的基础上,可以实现快速集成,也就是所谓的热插拔操作,可以无限对已经开发好系统进行扩展,而且不会影响已有的功能,不再需要的模块,通过修改配置移除即可。

插件化应用也是目前框架和系统开发的主流方向,从开发企业的产品管理角度来看,第一可以把控好已有的框架产品,第二可以把内部的人员分配到不同的业务模块中,让他们遵循一定的接口即可快速开发,从而提高团队对业务模块的横向切割和快速开发的效率,更好、统一、高效完成企业化应用框架的搭建和使用。

2、菜单支持动态配置,可根据用户权限进行动态控制显示

一般Winform程序中,菜单都是直接写在主程序中的,这样对于修改和维护菜单的相关信息,可能有所不便,而且对于插件化应用,新增菜单是常见的事情,这样就需要对菜单进行动态配置管理了,通过后台菜单的配置和权限的指定,能够实现菜单的动态加载和权限验证。

因此菜单也是权限分配的一部分,为了有效管理菜单资源,我们把菜单放到权限管理系统中进行管理控制。

图片 4

设定好菜单的图标和Winform窗体类型,就能在Winform框架中动态构建菜单信息了。菜单的图表放置在系统的相对目录下即可。

图片 5

图片 6

 

3、集成各种独立开发好的模块,如权限管理系统、字典管理模块等,自动更新模块等

 3.1 权限管理模块

权限的分配和管理,基本上是每个业务系统需要考虑的东西,而这些常用的东西,在整个Winform开发框架中,把它作为一个独立的模块,既方便维护管理,也留有接口很容易进行集成,这样能够在项目中反复进行使用。

权限系统需要考虑的系统用户、组织机构、角色、权限定义及分配、菜单管理、用户登录日志等相关信息。对于每新增一个系统,我们只需要在权限管理系统中增加一个系统类型定义,以及相关的功能、菜单数据即可,非常方便管理。

图片 7

3.2 字典管理模块

另外,除了权限的管理,字典管理也是常规业务模块的一个总要功能,因此字典管理模块在Winform开发框架中,也是一个独立的模块进行开发管理,在使用的时候进行集成即可。

字典的分类可以按多级进行分类管理,可以拖拉进入新的分类,非常方便。

图片 8

3.3 自动更新模块

一般情况下,为了有效管理应用程序的发布及更新,我们需要软件支持远程自动更新功能;在Winform开发框架中再引入一个自动升级更新的通用模块,这个自动升级的通用模块除了具备一般的功能外,可以通过配置程序标题、升级路径方式等方式,实现通用化的升级操作,其他需要升级的程序,拿过来就可以使用,经过项目的整合及优化,已经具备较好的应用前景了。

本通用自动更新模块具有下面几个特点:

1)程序标题可配置,更新路径可配置,适用于各种需要更新的项目整合。

2)支持文件复制或者对压缩包进行解压,适合更多琐碎程序集的整体升级。

3)支持文件更新后自动启动,或者带参数的启动方式。

图片 9

4、可重复使用的系统基础模块,Winform分页控件和.NET开发公用类库等

4.1 Winform分页控件

为了提高数据的获取及显示效率,一般情况下,我们都需要对数据进行分页获取和显示,在网络化环境,这种方式获取数据特别重要,在Winform里面,没有现成的分页控件可以使用,因此出于这个考虑,把数据显示、数据导出、数据打印等众多功能集成一起,更加方便使用。分页控件完美支持列表数据的分页,可以调整显示列及顺序,是否显示复选框,字段别名,奇偶列的颜色变化,列信息提示和数据复制等等众多实用细致的功能的。

列表的数据绑定及显示代码,通过代码生成工具,可以一键生成所需的界面代码,开发效率飞一般的提升。

图片 10

图片 11  

4.2 .NET公用类库

俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富的积累,都是助你走向成功,走向顶峰的推动力。就我们开发者而言,其中技巧的积累、资源的积累,就是类似一个个好汉、一根根好柴,是我们能够进行高效开发的保证和推动力。

这些类库是我从事多年软件开发,逐渐提炼和发现的一些闪光点或者好片段,有些是吸收别人的优秀的东西,有些是自己逐步提炼的精华,以前,在网络上看到一些开源的项目,总会先看看其是否有封装良好、功能独立的辅助类库,发现好的辅助类库,总是欣喜若狂好一阵子,学习中逐步积累,研究中逐渐提炼,多年过后,略有小成,终为今天所介绍的辅助类库集合。这些辅助类库平时也并不是所有的都会用得上,不过一些常用的,几乎各个项目就会用到,类库涉及面非常广,能够为我们开发节省很多时间,并且我们也可以根据自己的需要进行扩充完善,形成自己的类库集合。

博客公用类库在线帮助文档列表:

 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(1)—-开篇总结
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(2)—-常用操作
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(3)—-数据库相关操作
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(4)—-CSV、Excel、INI文件、独立存储等文件相关
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(5)—-热键、多线程、窗体动画冻结等窗体操作
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(6)—-全屏截图、图标获取、图片打印、页面预览截屏、图片复杂操作等
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(7)—–声音播放、硬件信息、键盘模拟及钩子、鼠标模拟及钩子等设备相关
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(8)—-非对称加密、BASE64加密、MD5等常用加密处理 
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(9)—-各种常用辅助类
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(10)—各种线程同步的集合类
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(11)—各种线程相关操作类
 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(12)—
网络相关操作辅助类

5、代码生成工具Database2Sharp的整合

整个框架通过与代码生成工具Database2Sharp进行配合,能够一键生成整体性框架代码,Winform系统界面代码,开发更高效。

图片 12

在整个Winform开发框架中,Database2Sharp生成出来的代码体现了非常完美的整合性,能够无缝接入开发的框架系统中,无论是常规的业务逻辑和数据访问层代码,以及一些列表、编辑界面的Winform界面代码,都能快速生成,稍作调整即可满足业务模块的需要。

Database2Sharp是一个简单点击几次鼠标就能完成一周代码量的代码生成工具,效率惊人、友好体贴,真正的开发好伴侣。提供了对SqlServer
2000、SqlServer
2005、Oracle、Mysql、Access、SQLite的支持;可以生成各种架构代码、Winform界面代码,并且和Winform开发框架完美整合,体现出更高的开发效率。

图片 13

6、通用的Excel数据导入导出,能快速导入自定义模块的Excel数据,快速导出列表数据

由于一般的业务系统,经常性的数据导入时很正常的业务需求,因为毕竟使用Excel来操作数据也很方便,或者由于系统之间的数据交换需要,我们需要提供一个入口给客户导入所需要的数据。但是导入数据的时候,不同的业务数据对应不同的Excel文件,很难做到统一,但如果是每个业务模型,都创建一个不同的导入界面来操作Excel数据,又会觉得可能某种程度上重复劳动,增加开发及维护成本。

那么有无一种介于两者之间的方法,来实现效率的最优化,并且能够统一利用好一个导入的界面呢,在开发领域,只要能想到的,一般也能做到,由于工作的需要,在我的Winform开发框架中引入了一个通用的数据导入模块,来实现这个既是统一,又是变化的业务需求。Winform框架提供的个通用的Excel数据导入导出机制,通过代码生成工具Database2Sharp自动生成的代码,就包含了如何使用这个通用导入模块的相关代码以及该模块的导出数据的代码,我们要做的就是在系统运行起来,导出一些数据作为某个模块的Excel模板即可。下面的功能按钮就是使用代码生成工具自动生成的界面包含的按钮。

图片 14

通用数据导入功能,包含下面几个方面的内容。

图片 15

下面就是一个实际生成的功能模块,其导入界面的运行效果。

图片 16

在最底的状态栏里面,但我们保存数据的时候,会调用后台线程进行数据保存,并显示数据导入的进度状态,由于是采用后台线程处理,不会阻塞当前的界面,在多文档的Winform开发框架界面中,可以切换到其他业务界面进行其他处理,不影响整体界面操作。

7、自定义Excel自定义模板报表的生成,生成各种复杂的Excel报表

很多情况下,我们需要生成比较专业的Excel模块,因此自定义模板报表就是一种很好的方案,Winform开发框架提供了多种自定义Excel报表的生成。

图片 17

使用普通的二维表,虽然能满足大多数的情况,不过在一般的业务中,自定义模板的报表根据贴近实际,符合客户的要求,虽然自定义模板的报表,比普通的二维报表复杂一些,不过利用Apose.Cell控件,并在预设模板中预设变量,可以生成很复杂的报表。

具体的自定义模板报表可以参考下我总结的两篇文章。

使用Aspose.Cell控件实现Excel高难度报表的生成(一)

使用Aspose.Cell控件实现Excel高难度报表的生成(二)

例如生成一个标准的出库单,这个表单有表头信息,列表数据信息,并非一个普通的二维表,而且这种格式比较固定,因此很适合自定义模块报表的生成操作。

图片 18  

 其他设计模板如下所示:

 

图片 19 

实际生成的报表如下所示:

图片 20

8、强大通用的统计图表模块,数据统计更方便

统计图表在很多项目都可能用到,集成到框架中,更方便大家对一些图表项目的设计理解以及功能的重用。在一般的传统的框架中,可以采用ZedGraph开源控件或者微软自带的MSChart进行图表设计,DevExpress控件套件有自己的图表控件,这里主要介绍基于DevExpress控件的图表控件进行图表设计。

8.1 普通统计图表

这里指的普通统计图表,只是对表某一项目进行单一的统计,可以从饼状图、柱状图的图表中体现这些项目各自所占的比例和数值,在Winform框架中的普通统计图表模块中,包括了饼状图、柱状图和数据表格,这样更方便对数据进行全面的分析和查看。整个模块是可以重用的,指定字段属性就可以比较合理的展现出不同分类项目的统计效果了,具体效果图如下所示。

图片 21

上面的统计图表中,还包含了下面两个功能模块,如下所示。

图片 22

图片 23

8.2 动态项目统计图表

有时候,对于表里面的数据,可能要对不同类型的内容进行动态的统计,以确定他们各自的比例情况,那么这些动态项目的统计图表就比较合适了,例如,对于病人资料的管理,可能需要统计各种病种所占的比例或者各种职业类型的犯病率,这些不太确定的统计项目,就需要一个能够支持动态项目的统计图表进行支撑,对于本Winform框架,为了较好呈现这个类型报表的意义,我选择了对备件类型所占的比例进行一个统计分析,得到下面的统计图表,如下所示。

图片 24

上面的图表统计,除了能够根据一些条件进行限定查询范围外,还可以对一些预设的统计字段进行动态选取,然后根据字段里面的各种内容(统计项目)进行统计,这样就可以比较有效的统计出各种类型的数值和比例了。

8.3 多重坐标对比统计图表模块

在Winform框架里面,可以对某一年各月份的出入库数量进行一个分析,得到下面的统计图。

图片 25

以上数据不多,展现可能不太好看,下面我给出我另一个软件系统的界面,其中对病人的出入院记录进行一个统计对比分析,统计报表如下所示。

图片 26

9、基于多数据库的数据查询模块和通用高级查询模块,查询数据更方便

在我的Winform开发框架中,使用了一个查询辅助类SearchCondition来实现查询条件的获取和转化,这个辅助类内置了对多种数据库条件的分析处理,因此能够很好生成所需要的数据查询条件,正确高效获取所需的数据进行显示。

        /// <summary>
        /// 根据查询条件构造查询语句
        /// </summary> 
        private string GetConditionSql()
        {
            //如果存在高级查询对象信息,则使用高级查询条件,否则使用主表条件查询
            SearchCondition condition = advanceCondition;
            if (condition == null)
            {
                condition = new SearchCondition();
                condition.AddCondition("ItemName", this.txtName.Text, SqlOperator.Like)
                    .AddCondition("ItemBigType", this.txtBigType.Text, SqlOperator.Like)
                    .AddCondition("ItemType", this.txtItemType.Text, SqlOperator.Like)
                    .AddCondition("Specification", this.cmbSpecNumber.Text, SqlOperator.Like)
                    .AddCondition("MapNo", this.txtMapNo.Text, SqlOperator.Like)
                    .AddCondition("Material", this.txtMaterial.Text, SqlOperator.Like)
                    .AddCondition("Source", this.txtSource.Text, SqlOperator.Like)
                    .AddCondition("Note", this.txtNote.Text, SqlOperator.Like)
                    .AddCondition("Manufacture", this.txtManufacture.Text, SqlOperator.Like)
                    .AddCondition("ItemNo", this.txtItemNo.Text, SqlOperator.LikeStartAt)
                    .AddCondition("WareHouse", this.txtWareHouse.Text, SqlOperator.Like)
                    .AddCondition("Dept", this.txtDept.Text, SqlOperator.Like)
                    .AddCondition("UsagePos", this.txtUsagePos.Text, SqlOperator.Like)
                    .AddCondition("StoragePos", this.txtStoragePos.Text, SqlOperator.Like);
            }
            string where = condition.BuildConditionSql().Replace("Where", "");
            return where;
        }

    /// <summary>
    /// Sql的查询符号
    /// </summary>
    public enum SqlOperator
    {
        [Description("Like 模糊查询")]
        Like,

        [Description("Not LiKE 模糊查询")]
        NotLike,

        [Description("Like 开始匹配模糊查询,如Like 'ABC%'")]
        LikeStartAt,

        [Description("= 等于号")]
        Equal,

        [Description("<> (≠) 不等于号")]
        NotEqual,

        /// <summary>
        /// > 大于号
        /// </summary>
        [Description("> 大于号")]
        MoreThan,

        [Description("<小于号")]
        LessThan,

        [Description("≥大于或等于号 ")]
        MoreThanOrEqual,

        [Description("≤ 小于或等于号")]
        LessThanOrEqual,

        [Description("在某个字符串值中")]
        In
    }

另外,一个好的数据查询
,一般有一个强大的高级查询模块,这个模块在很多程序中都很常见,也是给客户扩展查询的一个很好的补充,由于我一直希望我的Winform开发框架能够精益求精,所以做了这个通用高级查询模块,希望对今后我自己所有的项目以及框架本身,都能高效的使用。

图片 27

 在介绍输入条件的时候,我们注意到,查询输入,基本上可以分为几类:其一是常规的文本类型,使用文本框替代即可;其二是下拉列表类型,用户从列表下面选择内容;其三是日期类型,需要用户指定开始日期和结束日期;其四是数字类型,需要用户指定起始和结束的数值。

1)常规的文本类型条件输入界面:

图片 28

2) 下拉列表类型条件输入界面:

图片 29

3) 日期类型条件输入界面:

图片 30

4) 数字类型条件输入界面:

图片 31

10、框架提供基于多种数据库(Sqlserver/Oracle/Mysql/Sqlite/Access)的整合

虽然我们在实际项目中,一般采用一种数据库进行处理,但是不同的项目,采用的数据库类型可能不同,本Winform开发框架为了方便演示和扩展的需要,内置支持了Sqlserver/Oracle/Mysql/Sqlite/Access,更多的数据库,也可以通过扩展数据库访问基类的方式进行更多数据库的支持。

Winform开发框架里面的所有模块,如用到了数据存储的,如权限管理管理模块、通用数据字典管理模块,均内置支持这几种数据库的整合支持。整个Winform开发框架的数据库访问,能够手动配置数据库类型,对于同一种数据库,也可以把数据存储分开存储,如业务数据存储在一个数据库,权限管理控制存储在另外一个数据库这种方式。

图片 32

Winform开发框架提供多种数据库支持,数据访问基类依然很精简,因为我们利用的数据库访问模块是EnterpriseLibrary,把数据库抽象化,并且我把所有数据库通用操作放在了一个超级基类上,具体的数据库基类只需要实现变化的部分即可。业务访问类则使用泛型进行封装处理。

因此,Winform开发框架提供了高度封装的数据访问基类,开发代码更少更高效。

11、框架界面基类也进行统一封装,使用更方便,效果更统一

为了更好开发常用界面模块,Winform开发框架把一些公用的界面模块,统一放置在了一个BaseUI的项目中,把其中的通用高级查询、通用数据导入模块、常见处理界面基类,插件接口等模块放在一起,根据易于管理和使用。这样开发的模块,重用很多常规的界面,开发效率更快,使用更方便,效果更统一了。

图片 33

12、框架提供基础性的支持,包括集成登陆、闪屏、托盘功能,以及为插件模块提供登陆用户信息和系统信息

整个Winform开发框架,是有一个框架启动模块进行集中处理的,系统启动后,用户登录处理后,通过动态加载菜单和插件模块,并在主体框架界面中进行展示,提供权限控制和登录用户信息等方面的框架支持。另外框架支持闪屏图片的动态配置,系统激活热键和托盘缩小灯功能。

图片 34

由于系统登录后,框架本身存储了用户登录和权限信息,框架动态加载某个模块后,会把用户信息和权限控制信息,注入到模块的界面基类中,因此插件的界面模块只要是继承了BaseUI的界面基类,就能够获取到用户信息和权限控制信息了。

特性总结

Winform框架,本身就是为了能够快速开发一个高效、稳定、美观大方、扩展性强的应用软件系统。因此我在自己十年左右的共享软件开发生涯以及公司项目开发中,不断思考,精雕细琢,对很多重要的特性都进行了归纳和升华,吸收项目中好的闪光点,借鉴一些好的软件开发思路,力求把软件做的更好;在开发效率方面,除了开发一些常规通用的模块、在模块内部又充分考虑继承、重用的规则,还对大幅度提高效率的代码生成工具,根据Winform开发框架的实现思路和特点,进行了完善优化,使得无论在业务代码生成,还是在界面代码生成方面,均能把开发效率发挥到极致,希望整个Winform开发框架能够持续发挥它的魅力和吸引力,为更多的人带来希望,体验开发的乐趣。

相关文章