C/S简易UI框架开发总结(2)

       看了很多的回复,谢谢大家的关注!

       今天我想写个例子,简单说下如何使用这个框架开始新的项目并实现一个典型的CRUD功能。期间我还想说说关于各种UI组件间信息交互和调度方面的问题。这个组件一直在修修补补,基本稳定后也没有真正的仔细考虑过是否有更好的实现方式,通过简单的说明希望能把我的思路也理理清楚。大家也多多拍砖。

开始一个新的项目,首先要做的是创建一个主窗体,它直接从WorkbenchBase继承即可。

Partial Class MainForm

Inherits Component.WorkbenchBase

…………….

End Class

      完成上面代码后,就可以得到下图这样一个具备基本的菜单、手风琴和用户组件区的窗体。

由于业务功能没有具体实现,所以手风琴菜单什么都没有。而主菜单中除了与业务动作紧密关联的“编辑”菜单外,其他菜单项WorkbenchBase以默认提供。

主窗体有了以后,我们可以在实现一个典型的CRUD功能。

上一篇中以提到,实体编辑组件(EntityControl)用于处理一个业务实体的用户交互界面,一次做CRUD功能首先要创建一个自定义控件,然后修改代码,让他继承自EntityControl。

 

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _

Public Class MyEntityContorl

    Inherits Component.EntityControl

     …………….

End Class

而后需要把实体中的字段控件逐个定义到这个控件上,如下图

 

需要注意的是,为了能够完成组件与业务实体自动进行赋值和取值,要为需要进行数据交互的控件的Tag属性填写上相应的实体属性名。

 

如果实体组件上有需要数据绑定的组件,比如Combobox等,则重写InitBindableControl方法,把绑定的具体实现再在该方法内。

Public Class MyEntityContorl

    ''' <summary>

    ''' 实现可绑定组件的绑定方法

    ''' </summary>

    ''' <remarks></remarks>

    Public Overrides Sub InitBindableControl()

        MyBase.InitBindableControl()

    End Sub

End Class

实体组件通过反射调用相应的方法完成CRUD操作,默认方法名新增为“INSERT”,删除为“DELETE”,修改为“UPDATE”。如果需要变更相应方法名可以改写下面的属性。

Public Overrides ReadOnly Property InsertMethodName() As String

        Get

            Return MyBase.InsertMethodName

        End Get

    End Property

 

    Public Overrides ReadOnly Property UpdateMethodName() As String

        Get

            Return MyBase.UpdateMethodName

        End Get

    End Property

 

    Public Overrides ReadOnly Property DeleteMethodName() As String

        Get

            Return MyBase.DeleteMethodName

        End Get

  End Property

如果实体控件还需要提供额外的业务操作(如审核等),自己新增相应的方法即可。

此时的用户编辑组件并不知道他要编辑的业务实体对象是什么,由于大部分的CRUD操作在网格组件(GridView)中发起,此类场景下GridView会自动为用户编辑组件的DataSource赋值。在少数场景下,如果一个用户编辑组件需要独立使用,则需要自己编码为用户编辑组件设置DataSource和State(新增、修改、删除等状态)属性,以便用户编辑组件能够知道他要处理的实体对象和处理方法。如下面的代码:

 

            entityControlHost.State = New EntityControlHostAddNewState()

            entityControlHost.EntityControl.DataSource = r

到此为止一个实体编辑组件就完成了,他已经具备的与业务实体进行数据交互,CRUD的业务动作的自动调度等功能。由于重点在UI框架的介绍,具体CRUD的实现过程不再说明。

实际应用中,一个程序的界面组织形式有可能有两种显示方式:MDI和SDI。框架通过LayoutBehavier同时支持这两种方式,但是有些我们遇到的系统中的某些功能只能以MDI形式展现,由此可能造成有些SDI显示正常的组件在MDI中显示异常,因此我们需要为每个实体编辑组件定义一个容器,这个容器一方面可以提供SDI和MDI的支持,另外可以实现命令按钮,业务调度与实体编辑组件松耦合,避免重用的局限性。实体编辑组件的容器分为两类:EntityTabbedHost和EntityDialogHost,分被对应MDI和SDI。其中EntityDialogHost可以在MDI和SDI中系统自动甄别使用,EntityTabbedHost只能应用在MDI中。

那么就可以为MyEntityControl定义一个容器,

 

让这个组件集成EntityDialogHost,得到下面的窗体:

 

而后把刚才做好的实体编辑组件添加到这个窗体中。

  

并在代码中填写下面内容

Public Overridable Property EntityControl() As EntityControl Implements IEntityControlHost.EntityControl

        Get

            Return MyEntityControl1

        End Get

        Set(ByVal value As EntityControl)

            MyEntityControl1 = value

        End Set

End Property

此时,一个完整的实体编辑功能做完了。他已具备的保存、删除等基本的命令按钮,并实现了相应的调度功能,如果需要增加额外的业务命令,直接增加按钮并完成相应处理代码即可。

后面我们在做一个这个实体的网格组件,让这个功能更完整。

贴图太费劲了,很简单,我就文字描述了,首先定义一个自定义组件,让这个组件集成GridView,此时获得下面的控件。

 

使用设计器,添加相应的列,即可完成网格组件的定义。如果实体编辑组件中有额外的业务处理(如审核等),可以把他以菜单项的形式定义在编辑或系统中,后面框架会自动与主菜单合并。以保证框架业务调度和展现的一致性。

此时该组件已具备了网格自定义(列,条件样式等,其实这个很好做都是Janus组件的一个功能集成)及CRUD及其他业务功能的调度能力。

并且他不需要而外定义容易,因为系统会自动根据LayoutBehavier的MDI和SDI状态决定他的展现形式。

至此CRUD的功能都做完了,剩下就是拼装这个功能。

拼装过程原来是参照SharpDeveploer用插件做的,包括依赖关系等,后来感觉开发规模有限,调试也很麻烦就放弃了。

简单说下拼装过程,首先在一个业务功能对应着一个FolderItem,多个FolderItem构成一个Folder,一个Folder对应着主窗体上左侧手风琴菜单的一组。

为了把上面的业务功能增加到系统中,需要以下代码:

Public Class CustomerFolder

    Inherits Component.Folder

    Public Sub New()

        Init()

    End Sub

 

    Sub Init()

 

        Dim item As FolderItem

        item = New FolderItem

        Text = "XXXXX管理"

        ImageName = Application.StartupPath + "\images\basedata.bmp"

        item.FolderName = "XXXXX管理"

        item.FolderOrder = 1

        item.FolderGroup = "XXXXX管理"

        item.IconName = "small75.bmp"

        item.Subject = "XXXXX管理"

        item.ViewFullName = "CustomerView"

        item.BusinessServiceFullName = "DAL.CustomerProvider"

        item.BusinessMethodFullName = "GetAll"

        AddFolderItem(item)

    End Sub

End Class

而后在MainForm(Workbench)中重写CreateFolders()方法

Public Overrides Function CreateFolders() As Component.FolderKeeper

        Dim folders As New Component.CustomerFolder

        Dim b As BaseFolder = New BaseFolder

        folders.Add(b)

        Return folders

End Function

其实上面的信息之前是卸载配置文件或数据库里,那样就代码整洁些,但是可读性会稍差,改成这样也不满意,纠结。

下面完成启动代码,就大功搞成了~

  ''' <remarks></remarks>

    Public Sub Main()

        Application.SetCompatibleTextRenderingDefault(False)

        Application.EnableVisualStyles()

 

        Dim mainForm As New MainForm

        mainForm.BusinessBehavier =  New WcfBusinessBehavier

        mainForm.LayoutBehavier =  New TabbedLayoutBehavier

        mainForm.ServiceManager = New Component.ServiceManager

        mainForm.ServiceManager.ValidateService = New ValidateService

       '其他服务和Bevhavier暂时不需要,不写了 

        System.Windows.Forms.Application.Run(mainForm)

End Sub

当然完美的话很多工作要做,但是基本的功能都说明就可以了。运行一下吧:

 

最简单的CRUD就这么做了,省去了很多赋值取值的麻烦,界面风格统一了,业务功能一致性有保障而且所有调度功能都不用重复写。

还是那句话,抛砖引玉,欢迎大家用力扔玉,最好是蓝田玉,呵呵。

posted @ 2011-03-10 18:14  大道至简(- -)  阅读(4606)  评论(22编辑  收藏  举报