zoukankan      html  css  js  c++  java
  • ASP.NET Web开发框架之五 设计时支持,代码生成,数据字典 ExtAspNet控件扩展

    设计时支持

    当在Web页面中设计好表格布局之后,运用Enterpris Solution提供的框架,以可视化的方式绑定数据。

    首先,请在配置文件中添加如下的程序集引用,以方便框架运用反射找到当前项目所引用的实体层。

     <appSettings>
        <add key="Assembly" value="E:\Solution\Enterprise Solution\Build\Benin.BusinessLogic.dll"/>
      </appSettings>

    然后打开Visual Studio,在设计时面板中,选择一个控件。

    image

    如上图所示,选择控件的DataBindingString属性,在属性面板中打开它。如果已经绑定了属性,它会自动高亮显示已经绑定的实体及其属性。这个属性的代码设计,是这样的

    [Category(CategoryName.OPTIONS)]
    [DefaultValue("")]
    [Description("Data Binding")]
    [Editor(typeof(QueryBindingTypeDialogEditor), typeof(UITypeEditor))]
    public virtual string DataBindingString
     {
                get
                {
                    object obj = XState["DataBindingString"];
                    return obj != null ? obj.ToString() : "";
                }
                set
                {
                    XState["DataBindingString"] = value;
                }
    }

    如代码所示,它提供了一个自定义的属性编辑器,也就是上图中我们看到的Query Builder,绑定属性。

    返回所需要绑定属性的关键代码如下所示,它读取实体层程序集并返回用户所选择的属性值

    string path = "";
    IWebApplication webApp = (IWebApplication)provider.GetService(typeof(IWebApplication));
    Configuration config = webApp.OpenWebConfiguration(true);
    AppSettingsSection app = config.AppSettings;
    path = app.Settings["Assembly"].Value;

    这几句代码的含义,从当前Web项目中打开Web.config配置文件,并找到文章开头设置的实体层程序集。

    代码生成

    基于模板的代码生成器,例如Code Smith,给代码生成带来了极大的便利。Enterprise Solution相关的代码生成,均以Code Smith模板完成。熟悉ASP.NET的语法,应该可以很快熟悉Code Smith的语法并对它的生产力感到满意。

    image

    在最新版本的Code Smith 6.5中,支持.NET 3.x/4.0语法。还可以运用它的SDK,把代码生成功能集成到自己的开发工具中。比如,我想制作一个批量代码生成的工具,直接调用Code Smith的模板文件:

    public  void RunTemplate(string templateFile,string connectionString,string tableName,string targetFile)
    {
                CodeTemplateCompiler compiler = new CodeTemplateCompiler(templateFile);
                compiler.Compile();
    
                if (compiler.Errors.Count == 0)
                {
                    CodeTemplate template = compiler.CreateInstance();
                   
                    DatabaseSchema database = new DatabaseSchema(new SqlSchemaProvider(), connectionString);
                    TableSchema tableSchema = database.Tables[tableName];              
    
                    //如果都是字符串,应该要考虑bool,int,object
                    Dictionary<string, object> dic = new Dictionary<string, object>();
                    string[] paramterValues = rtfParameter.Lines;
                    foreach (string parm in paramterValues)
                    {
                        if (!String.IsNullOrEmpty(parm))
                        {
                            string[] values = Regex.Split(parm, "=");
                            string key = values[0];
                            object para =values[1].ToString().Trim();
                            if (string.IsNullOrEmpty(values[1]))
                                para = tableSchema;
    
                            dic.Add(values[0], para);
                        }
                    }
                    PropertyInfo[] pis = template.GetProperties();
                    foreach (PropertyInfo pi in pis)
                    {
                        object val=null;
                        if(dic.TryGetValue(pi.Name,out val))                    
                          template.SetProperty(pi, val);
                    }   
          
                    if(File.Exists(targetFile))
                        File.Delete(targetFile);
                    using (StreamWriter writer = new StreamWriter(targetFile))
                    {
                        template.Render(writer);
                        writer.Flush();                    
                    }
            }
    }

    这个方法可以为你的代码生成带来诸多方便。比如以下面的参数调用之,则可以产生多个代码文件

    RunTempate("Interface.cst","server=(local);uid=sa;pwd=holiday;database=TS","Employee","IEmployeeManager.cs)
    RunTempate("Manager.cst","server=(local);uid=sa;pwd=holiday;database=TS","Employee","EmployeeManager.cs);

    每行产生一个代码文件,接口层和数据访问层立即产生完成。

    数据字典

    对于不变的数据字典,比如帐户的借方和贷方,程序员每天的工作分类项:Bug或Enhacement。对于这类不变的数据字典,Enterprise Solution以下面的方式处理它们。

    先来看界面层的代码,看看最终的开发人员,需要以何种方式应用数据字典。以客户组别为例子

    <ext:DropDownList ID="ddlCustomerGroup" Label="Customer Group" runat="server"> </ext:DropDownList>

    后台代码如下所示,也相当的简练

    ddlCustomerGroup.InitializeValueListFromEnum(typeof(CustomeGroup));

    在此,我并没有直接扩展DropDownList的代码,而是加入扩展方法,它的实现方法如下所示

      public static class DataBindingHelper
        {
            public static void InitializeValueListFromEnum(this ExtAspNet.DropDownList dropDownList, Type enumType)
            {
                dropDownList.Items.Clear();
                foreach (KeyValuePair<string, string> item in StringEnum.GetValueStringList(enumType))
                {
                    ExtAspNet.ListItem listitem = new ExtAspNet.ListItem(item.Value, item.Key);
                    dropDownList.Items.Add(listitem);
                }
            }
    }

    代码的意图相对简单,依据参数的枚举值分别产生ListItem达到生成数据字典项的目的。枚举CustomerGroup的定义

    public enum CustomeGroup
    {
            [StringValue("Partner")]
            [DisplayText("Partner")]
            Partner,
    
            [StringValue("Supplier")]
            [DisplayText("Supplier")]
            Supplier
    }

    StringValue和DisplayText分别用于ListItem的ValueItem和TextItem,用于显示和实际的值。

    对于需要从数据库中取出的数据字典,Enterprise Solution框架暂未提供很方便的方法来完成绑定。依照基本的方法,读取字段值,绑定到DropDownList中,过程也不复杂。

    ExtAspNet控件扩展

    ExtAspNet是一套优秀的控件,用它可以快速开发基于ExtJs的应用。虽然功能相当完善,但在细微处,仍需要稍微做一些调整,以满足框架的应用需要。

    每一个需要绑定属性的控件,均加入了下面的属性,以方便绑定实体的属性。

    [Category(CategoryName.OPTIONS)]
    [DefaultValue("")]
    [Description("Data Binding")]
    [Editor(typeof(QueryBindingTypeDialogEditor), typeof(UITypeEditor))]
    public virtual string DataBindingString
            {
                get
                {
                    object obj = XState["DataBindingString"];
                    return obj != null ? obj.ToString() : "";
                }
                set
                {
                    XState["DataBindingString"] = value;
                }
        }

    其次,我需要TextBox的文本标签是右对齐的,而不是左对齐,于是加入了下面的属性。

    //fieldLabel居右对齐的问题 
    OB.AddProperty("labelStyle", "text-align:right");     

    对于页面中的每个选项卡页面,我需要在它关闭时,弹出提示确认窗口,于是修改代码

     NODES.mainTabStrip.addTab({
            'id': tabID,
            'url': url,
            'title': title,
            'closable': true,
            listeners: {  
                     'beforeclose': conrirmTab  
                }
             });

    加了一个beforeclose确认,它的方法如下所示

    function conrirmTab(e) {
        Ext.MessageBox.show({
            title: 'Confirm',
            msg: 'Are you sure want to close  <b>' + e.title + '</b> ?',
            buttons: Ext.MessageBox.YESNO,
            icon: Ext.MessageBox.QUESTION,
            fn: function (btn, text) {
                if (btn == 'yes') {
                    NODES.mainTabStrip.remove(e);
                }
            }
        });
        return false;
    }

    更精确的,我们应该加在那些有数据修改的页面,如果页面被修改过,则弹出确认提示,否则可以直接关闭选项卡。

    再来看看两个比较实用的脚本,关闭当前选项卡和关闭所有选项卡

    //关闭活动的选项卡
    function closeActivePanel() {
                var tabpanel = Ext.getCmp('<%= mainTabStrip.ClientID %>');
                var _activeTab = tabpanel.getActiveTab();
                if (_activeTab.x_iframe_url == "/Management/admin/default.aspx")
                    return;
                tabpanel.remove(_activeTab);
    }
    
    //关闭所有选项卡
    function closeAllPanel(){
                var tabpanel = Ext.getCmp('<%= mainTabStrip.ClientID %>');
                var _activeTab = undefined;
                for(var i=0;i< tabpanel.items.length;i++)
                {
                     _activeTab = tabpanel.items.items[i];
                     if (_activeTab.x_iframe_url!=undefined && _activeTab.x_iframe_url == "/Management/admin/default.aspx")
                        continue;
                     tabpanel.remove(_activeTab);
                     i = 0;
                }
                tabpanel.doLayout();
    }

    如果需要在后台代码中调用,可以这样调用之

    string tab = "closeAllPanel();";
    PageContext.RegisterStartupScript(tab);

    还有一些控制项,有的还未找到实现方法,一并列举如下

    1  控制TextBox的输入长度。比如maxLength=6,只允许输入6个字符,第7个字符无法输入。当前控件仍然可以输入,只是会有验证提示错误。

    2  只允许大写字母输入。有的控件,比如用户名,在C#.NET里面,MIS和mis的字母相同,但是比较equal时,如果不设置忽略大小写,则它们的值不等,但是在数据库里面,它们是相同的值。为避免这种情况,我需要设置控件只允许输入大写字母,用户如果输入的是小写,则转化自动为大写。

    3  对于Tab.cs #267行,这一行代码会有异常。如果前台JS打开多个选项卡,在页面刷新时,会抛出IndexOutOfRange异常,它的代码如下所示

    // 对于非激活Tab,其中的Iframe需要延迟加载
     if (this != tabStrip.Tabs[tabStrip.ActiveTabIndex])
                    {
                        OB.RemoveProperty("html");
                        OB.RemoveProperty("x_iframe_loaded");
                        OB.AddProperty("x_iframe_loaded", false);
     }

    ActiveTabIndex的值是2或3,但是当前只有一个tab选项卡,于是抛出索引越界异常。

    4 PageRefresh时,会关闭前台页面打开的选项卡。需要用cookie记住已经打开的选项卡,在PageRefresh后,再打开被迫关闭的选项卡,以减少用户困扰。

    5 对ascx用户控件的支持。新版本的ExtAspNet已经内置了此功能。如果仍使用的是3.1.8版本,需要这样

    foreach (UserGroupMenuTypeEntity usermenuType in menu.UserGroupMenuTypes)
    {
                    function c = LoadControl("function.ascx") as function;
                    c.LineBreakPlaceHolder.Text =GetTranslation(usermenuType.Description.Replace("&", ""));
                    c.DataList1.DataSource = usermenuType.UserGroupMenuDetails;
                    c.DataList1.DataBind();
                    ph.Controls.Add(c);
    
                    Literal liter = new Literal();
                    liter.Text = "<br />";
                    ph.Controls.Add(liter);
    }

    加载用户自定义控件。因为Web不同于WinForms,Web的类型定义并不包含资源,图片,控件,还必须引用页面ASPX/ASCX文件,C/S类型的继承则包含类型的方法,及其界面控件,相对方便很多。

    6 Excel导入导出的支持。官方的例子中已经包含EXCEL导出功能,但没有导入功能,仍然需要提供Web方式下的EXCEL数据导入功能。

     
           
  • 相关阅读:
    存储器结构、cache、DMA架构分析--【原创】
    驱动开发--【字符设备、块设备简介】【sky原创】
    如何在博客园上面显示自己定义的头像--【sky原创】
    程序执行的过程分析--【sky原创】
    如何在linux下检测内存泄漏(转)
    register 用法注意与深入--【sky原创】
    volatile的深入理解--【sky原创】
    【sky第二期--PID算法】--【智能车论坛】
    滤波电容的选择
    实现开发板与ubuntu的共享--根文件系统NFS--Samba共享【sky原创】
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/2703361.html
Copyright © 2011-2022 走看看