• 知识管理系统Data Solution研发日记之六 窗体设计器


    知识管理系统Data Solution已经有五篇文章对它进行介绍,可以通过下面的连接,找到前面的文章

    知识管理系统Data Solution研发日记之一 场景设计与需求列出

    知识管理系统Data Solution研发日记之二 应用程序系列

    知识管理系统Data Solution研发日记之三 文档解决方案

    知识管理系统Data Solution研发日记之四 片段式数据解决方案

    知识管理系统Data Solution研发日记之五 网页下载,转换,导入

    每一篇文章都试图从一个角度来分析这个系统的目的,设计思路。至于源代码,并没有什么特别的难度,问题的关键在于思路,找到了合适的解决方案,实现起来就相对容易一些。这篇文章讲解窗体设计器的主要内容。

    image

    设计器生成的的窗体文件,可以以二种方式保存,一种是源代码方式,C#,VB.NET代码的形式,另一种是XML格式,这里采用的是XML格式保存窗体设计格式。如果你对此并不熟悉,请通过查看文章《基于窗体设计器的企业管理软件开发工具》来了解更多的内容。

    在Windows Forms的开发中,BindingSource控件扮演着数据与控件连接的桥梁,而且是双向的数据绑定。这句话在学习ASP.NET时,一直不得其解,双向的数据绑定与单向的有什么区别。用直白的话说,双向的数据绑定,可以让控件中被用户修改的数据,重新写到绑定的数据源中,在窗体的保存功作中,可以保存用户修改的数据。双向的数据绑定可以节省大量的数据绑定代码,想像一下,在刚学编程时,经常写出这样的代码

    protected override void OnLoad()
    {
        txtUserName.Text=user.UserName;
        txtEmal.Text=user.Email;
    }
    
    protected override void OnClosing()
    {
          user.UserName=txtUserName.Text;
          user.Emal=txtEmail.Text;
    }

    在窗体打开时,需要从数据实体类型中,绑定数据到控件中,在窗体关闭时,再从控件的值写到数据实体类型中。如果没有双向的数据绑定,界面中会大量的重复这样的代码。

    先来看一个,读取单一个数据表的情况。比如,只读取采购单PUORDH一个表。在上图中的窗体设计器中,有两个FlexDataTable控件,它用来获取数据源。它的Name就是数据库中的表名,SQL属性是读取数据的SQL语句,比如有一个表是PUORDH(采购单),那么需要为它写SQL属性为SELECT * FROM PUORDH。理论上,在知道表名之后,是不需要写SQL属性的,因为可以生成默认的SELECT语句,出于效率的考虑,可以简化对SQL的编写,比如上面的窗体,它只读取PUORD的Ref No.和Vendor,这时,如果自动生成的SQL语句还是SELECT * FROM PUORDH,则效率损失很多,其它的不需要的字段也被读取到内存中。所以,FlextDataTable的SQL属性,可来用优化SQL性能,当它的值是空时,窗体设计器会自动生成SELECT * FROM PUORDH。

    再来看一下,读取主从表的情况。如上图所示,主表PUORDH,明细表PUORDD,它们的关系存在于数据库中,是一对多关系。这时,数据绑定的关键代码是这三行

    this.bsH.DataSource = this.DataSet;
    //this.bsD.DataSource=this.DataSet;
    this.bsD.DataSource =bsH;
    this.bsD.DataMember = "FK_PUORDD_PUORDH";

    表头的数据仍然是DataSet,初试化窗体时,根据FlexDataTable表名和它的SQL属性,读取数据到DataSet中。从表的数据如果是DataSet,没有错,但是没有正常显示出主表与从表的数据关联数据,它会选出所有的从表数据。所以,后面两行代码是绑定从表数据的关键。窗体设计器在生成CS源代码时,则需要生成正确的主从数据关系绑定代码。

    在生成主从数据关系方面,XSD是首选的方案,参考下面的调用代码,它可以生成包含关系的XSD文件

    string connectionString = "data source=(local);initial catalog=Emp5;integrated security=SSPI;persist security info=False;packet size=4096";
    string destinationFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, xsdName);
    
    List<string> tables = new List<string>();
    foreach (IComponent comp in host.Container.Components)
           {
                    if (comp is FlexDataTable)
                     {
                                 tables.Add(comp.Site.Name);
                        }
            }                       
    DatasetGeneratorForm dlgXsd = new DatasetGeneratorForm(connectionString, destinationFile, false, "CS", tables);
    dlgXsd.GenerateXsdSource();

    窗体设计器正是从这个生成的XSD文件中获取到表与表之间的关系,以生成上面提到的主从表的数据绑定代码。

    在窗体设计器生成代码方面,CodeDom是首选的代码生成技术。这主要归咎于它可以以一套代码,同时生成C#,VB.NET两套代码,这种灵活性比硬编码的字符串拼凑,效果要好很多。代码示例如下

    //this.DataAdapter = da;
    CodeVariableReferenceExpression da = new CodeVariableReferenceExpression("da");
    CodePropertyReferenceExpression thisda = new CodePropertyReferenceExpression(new        CodeThisReferenceExpression(), "DataAdapter");
    CodeAssignStatement  as1 = new CodeAssignStatement(thisda, da);
    method.Statements.Add(as1);    

    为了写一个赋值语句,竟然用了四行代码,而且CodeDom调试时,也不可以看到它生成的目标代码的模样。这与调试带参数的SQL语句的体验差不多,无法得知最终要发送到服务器的SQL语句的模样。好在有MSDN和大量的在线资源,可以很容易的获取到一个C#语句如何用CodeDom表达出来。而且大部分情况是,你写对了CodeDom语句,感觉对了,它运行时的结果,就是对的。微软的人真了不起,竟然创造了CodeDom这种威力巨大的代码生成技术。

    再来看一下窗体间互操作的代码,打开一个窗体,可以用这条语句

    =Open("PURCHASE") 或是=Open("PURCHASE",this)

    带一个参数的Open方法,会以参数为XML文件名,拼凑成PURCHASE.XML字符串,到系统的指定目录中查找PURCHASE.XML窗体定义格式文件,读取并转化成窗体类型,显示出来;带二个参数的Open方法,会在系统指定的目录中,查找PURCHASE.dll程序集文件,反射它的类型成员,调用并显示了出来。这里也有个约定,窗体设计器生成的源代码文件,只包含一个类型定义,然后经过CodeDomProvider编译,生成窗体的程序集文件。

    继续看窗体设计器设计的窗体,它的另外几个按钮的Click事件的写法

    保存按钮的Click事件的写法是:=Save();

    删除按钮的Click事件的写法是:=Delete(bsH,bsD) ;

    创建按钮的Click事件的写法是:=New(bsH,bsD);

    在这里,完全不需要指定主外键,或是表与表之前的关联关系,所以这些,都由后台程序自动判断。这样做,也没有效率。读取数据的操作是把它读到一个DataSet中,然后依照FlexDataTable表名依次分配与绑定;保存操作会把数据写回到数据库中,依照DataSet中数据是否发生改变,这个写回数据库的过程,效率很低。当然,大多数的情况,是用来查看数据库中的数据,而不是编辑数据,依照这个标准,窗体设计器也达到了它的目的。

    把这几条技术整合到一起,就完成了窗体设计器的开发。我在思考这些关系时,通常零乱的,不完整的,设计的过程也是代码演化,思路调整的过程。也许你不知道我这里讲的是什么内容,或许你有更好的实现方法,欢迎反馈。

  • 相关阅读:
    1024X768大图 (Wallpaper)
    (Mike Lynch)Application of linear weight neural networks to recognition of hand print characters
    瞬间模糊搜索1000万基本句型的语言算法
    单核与双核的竞争 INTEL P4 670对抗820
    FlashFTP工具的自动缓存服务器目录的功能
    LDAP over SSL (LDAPS) Certificate
    Restart the domain controller in Directory Services Restore Mode Remotely
    How do I install Active Directory on my Windows Server 2003 server?
    指针与指针变量(转)
    How to enable LDAP over SSL with a thirdparty certification authority
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/2225492.html
Copyright © 2020-2023  润新知