窗体的复用----窗体继承

众所周知,在面向对象的软件开发中,通过对类的封装和抽象,可以对类进行继承,从而实现代码复用和增加软件的可维护性。那么,窗体能不能继承呢?在重构机房收费系统的时候遇到了如下问题:

相似的几个功能,窗体布局一模一样,如果使用以前的方法,只能复制、粘贴这些窗体和控件,可是,控件可以复制,名字却不能复制;如果改其中的一项数据的话,需要修改好几个窗体,可维护性差;U层、B层、D层代码相似度很高,代码复用性太低等等。怎么解决这些问题呢?

类可以进行抽象、封装,然后可以继承以复用,窗体能不能看做一个特殊的类?窗体和控件的属性是这个窗体类的属性,窗体和控件的事件就是这个窗体类的部分方法。完成了窗体类的抽象,就可以对这个窗体进行继承了。

具体实现过程:

1 按照正常步骤创建父窗体;创建原则是把需要复用的控件布置好;需要复用的代码也写到父类中;不需要复用的代码即子窗体不相同的数据需要在父窗体中写成虚函数。

父窗体如下:

2实现窗体复用功能代码:(以收取金额和退换金额为例)

首先是实体层代码,实体层代码包括所有父窗体和子窗体需要使用到的变量(不一定跟数据库相同)。这里就不再啰嗦。

U层代码:实现接收用户输入数据和输出数据功能。

Public Class frmMDICheckCash
    '退出
    Private Sub btnQuit_Click(sender As Object, e As EventArgs) Handles btnQuit.Click
        Me.Close()
    End Sub
    '导出为Excel,这里将导出EXCEL功能做成了一个模块,直接调用即可
    Private Sub btnExport_Click(sender As Object, e As EventArgs) Handles btnExport.Click
        Call ExportExcel.ExportExcel(DataGridView1)
    End Sub
    '查询数据方法
    Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
        '实例化一个实体类
        Dim enmdicheckcash As New Charge.Entity.MDICheckCash
        enmdicheckcash.StartTime = CStr(DateTimePicker1.Text.Trim)
        '获得两个日期字符串
        enmdicheckcash.OverTime = CStr(DateTimePicker2.Text.Trim)
        '将表名作为一个虚函数
        enmdicheckcash.SearchTable = GetTable()
        '实例化B层类
        Dim mdicheckcash As New Charge.BLL.MDICheckCash
        Dim myList As List(Of Charge.Entity.MDICheckCash)
        myList = mdicheckcash.CheckCash(enmdicheckcash)
        '通过B层返回值判断是否查询成功
        If myList.Count = 0 Then
            MsgBox("信息查询错误,请重新选择!")
        Else
            DataGridView1.DataSource = myList
        End If
    End Sub
    '将数据库的表名作为一个虚函数,因为子窗体需要查询的数据表不同
    Protected Overridable Function GetTable() As String
        Return ""          '子窗体需要继承并实现这个方法
    End Function
End Class

代码分析:两个子窗体功能不同,需要使用的数据表也不一样,所以要把表名作为一个变量,变量需要在U层赋值,所以需要做成实体。U层把获得表名作为一个虚方法,运行的时候进行赋值,然后将表名放到实体中,在D层使用。

因为B层、接口层和工厂层代码没有特殊之处,这里不再展示。

接下来是D层代码:

Imports System.Data.SqlClient
Imports System.Configuration
Imports Charge.DAL.sqlHelper
Public Class SQLServerMDICheckCash : Implements Charge.IDAL.IMDICheckCash

    Public Function SelectInfo(enmdicheckcash As Charge.Entity.MDICheckCash) As List(Of Charge.Entity.MDICheckCash) Implements IDAL.IMDICheckCash.SelectInfo
        Dim help As New Charge.DAL.sqlHelper
        Dim strSQL As String
        Dim median As DataTable
        '存储过程调用
        strSQL = "PROC_MDICheckCash"
        Dim sqlPara As SqlParameter() = {
        New SqlParameter("@TableName", enmdicheckcash.SearchTable),
        New SqlParameter("@StartTime", enmdicheckcash.StartTime),
        New SqlParameter("@OverTime", enmdicheckcash.OverTime)
        }
        median = help.ParaSelect(strSQL, CommandType.StoredProcedure, sqlPara)
        '将表格转换为实体集合返回B层
        Dim myList As List(Of Charge.Entity.MDICheckCash)
        Dim mhelp As New Charge.Entity.ModeHelper
        myList = mhelp.convertToList(Of Charge.Entity.MDICheckCash)(median)
        Return myList
    End Function
End Class

代码分析:D层带式实现了数据库查询功能,这里调用了sqlhelper和实体转换模块,并且使用存储过程来实现数据查询功能。存储过程使用了三个参数,表名和两个日期,最后返回一个实体集合。

创建子窗体:在创建子窗体的时候需要选择“继承的窗体”,然后选择继承的父窗体即可。子窗体代码:

Public Class frmCollectCash
    Dim enmdicheckcash As New Charge.Entity.MDICheckCash
    Protected Overrides Function GetTable() As String
        ' 给实体赋值
        enmdicheckcash.SearchTable = "dbo.Recharge_Info"
        Return enmdicheckcash.SearchTable
    End Function
End Class

代码分析:子窗体只需要实现父窗体中的虚方法即可,这里只有一个虚方法(获得表名),直接复制即可实现。

存储过程代码不予展示。

总结:窗体的继承大大减少了工作量,增加了系统的可维护性,减少了代码的冗余,但是也使系统的结构更加复杂。

思想:遇到问题不可怕,只要分析得当,总会找到解决方法的。

窗体的复用----窗体继承,布布扣,bubuko.com

时间: 2024-10-29 19:13:30

窗体的复用----窗体继承的相关文章

C#项目间复用窗体

在不同项目间可能使用相同的窗体.  复用窗体操作: 1.复制窗体文件, 一般包括三部分 2.粘贴到目标工程文件夹下 3.添加现在有项,选择cs文件即可 注意: 如果目标是dll项目,可先新建一个窗体,然后在添加复制来的窗体,最后删除新建窗体即可.如直接添加会出错. 原文地址:https://www.cnblogs.com/52vsto/p/12246124.html

公共事件,修改主窗体和子窗体的(主题)样式

主窗体修改主题样式时,同时修改子窗体的主题样式 系统展示效果: 一.项目结构 二.代码分析 SetAllFormStyle 界面对象参数 /// <summary> /// 编写:yj /// 日期:2014-08-14 /// 描述:系统界面参数 /// </summary> public class SetAllFormStyle: System.EventArgs { public C1.Win.C1Ribbon.VisualStyle autoStyle { get; se

附实例!实现iframe父窗体与子窗体的通信

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由前端林子发表于云+社区专栏 本文主要会介绍如何基于MessengerJS,实现iframe父窗体与子窗体间的通信,传递数据信息.同时本文会提供一个可运行的实例代码,实现在父窗体中,获取到来自子窗体的数据的效果. 0.背景介绍 (1)需要在当前的前端项目中,使用iframe嵌套别的站点页面. (2)当子窗体触发了一个事件后,要给父窗体传一个跳转地址的url.父窗体监听到这个事件后,根据接收到的url,来更新当前父窗体的url,实现页

winform 移动窗体,和窗体阴影(引用)

无边框窗体移动://窗体移动API [DllImport("user32.dll")] public static extern bool ReleaseCapture(); [DllImport("user32.dll")] public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int IParam); public const int WM_SYSCOMMAND = 0x

子窗体、父窗体方法互调

var childWindow = $("#editFrame")[0].contentWindow;//获取子窗体的window对象. childWindow.subForm(); $("#editFrame")得到frame [0].contentWindow//frame的子窗体,将JQUERY对象转化为DOM对象 subForm();//字窗体定义的方法 ----------------------------------------------------

winfrom 基类窗体与子类窗体load事件详解

今日在写代码时,需要在子窗体运行时调用基类窗体中的load事件,顺带将该部分功能做一个详细的了解. Winform窗体在初始化到呈现在用户眼前会依次经历三个阶段,构造-加载-显示,分别对应.NET 窗体中的 InitializeComponent,onLoad,show三个调用函数,以下: InitializeComponent:初始化窗体及窗体上的控件,加载并分配资源,注册相关事件 onLoad:注册装载窗口事件,是窗体启动时调用该函数,触发formload事件,从而调用From_Load事件

2016.6.18主窗体、子窗体InitializeComponent()事件、Load事件发生顺序以及SeleChanged事件的发生

主窗体,子窗体的InitializeComponent(构造函数).Load事件执行顺序 1.主窗体定义事件 new 主窗体() 构造函数进入主窗体InitializeComponent函数,该函数中有各字框体的new创建语句,因此: 2.依次执行各子窗体InitializeComponent函数 3.主窗体new事件结束后,并不创建任何窗体或子窗体,也就没有任何Load事件发生.直到主窗体Show事件. 4.主窗体Show事件后,顺序执行各子窗体Load事件,注意!!并不是先执行主窗体Load

Winfrom子窗体刷新父窗体

本人比较懒,直接从网上转载了一篇比较合适的文章,只是文章格式有点乱,地址是 http://aspnet.blog.163.com/blog/static/17515510920121126104433237/ 调用窗体(父):Form1,被调用窗体(子):Form2 方法1:   所有权法//Form1://需要有一个公共的刷新方法public   void   Refresh_Method(){//...}//在调用Form2时,要把Form2的所有者设为Form1Form2   f2   =

.Net子窗体给父窗体传值的几种方法

其实方法有很多种,这里只介绍3种,大家如有更好的方法可互相学习学习. 1.子父窗体Owner设定法: Form1: void Button_fm1_Click(object sender, EventArgs e) { Form2 fm2 = new Form2(); fm2.Owner = this;   //将Form2的Owner指针指向Form1 fm2.ShowDialog(); } Form2: void Button_fm2_Click(object sender, EventAr