ASP.NET Web开发框架之五 控件扩展

开发 后端
当在Web页面中设计好表格布局之后,运用Enterpris Solution提供的框架,以可视化的方式绑定数据。首先,请在配置文件中添加如下的程序集引用,以方便框架运用反射找到当前项目所引用的实体层。

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

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

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

image 

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

  1. [Category(CategoryName.OPTIONS)]  
  2. [DefaultValue("")]  
  3. [Description("Data Binding")]  
  4. [Editor(typeof(QueryBindingTypeDialogEditor), typeof(UITypeEditor))]  
  5. public virtual string DataBindingString  
  6.  {  
  7.             get 
  8.             {  
  9.                 object obj = XState["DataBindingString"];  
  10.                 return obj != null ? obj.ToString() : "";  
  11.             }  
  12.             set 
  13.             {  
  14.                 XState["DataBindingString"] = value;  
  15.             }  

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

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

  1. string path = "";  
  2. IWebApplication webApp = (IWebApplication)provider.GetService(typeof(IWebApplication));  
  3. Configuration config = webApp.OpenWebConfiguration(true);  
  4. AppSettingsSection app = config.AppSettings;  
  5. 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的模板文件:

  1. public  void RunTemplate(string templateFile,string connectionString,string tableName,string targetFile)  
  2. {  
  3.             CodeTemplateCompiler compiler = new CodeTemplateCompiler(templateFile);  
  4.             compiler.Compile();  
  5.  
  6.             if (compiler.Errors.Count == 0)  
  7.             {  
  8.                 CodeTemplate template = compiler.CreateInstance();  
  9.                  
  10.                 DatabaseSchema database = new DatabaseSchema(new SqlSchemaProvider(), connectionString);  
  11.                 TableSchema tableSchema = database.Tables[tableName];                
  12.  
  13.                 //如果都是字符串,应该要考虑bool,int,object  
  14.                 Dictionary<stringobject> dic = new Dictionary<stringobject>();  
  15.                 string[] paramterValues = rtfParameter.Lines;  
  16.                 foreach (string parm in paramterValues)  
  17.                 {  
  18.                     if (!String.IsNullOrEmpty(parm))  
  19.                     {  
  20.                         string[] values = Regex.Split(parm, "=");  
  21.                         string key = values[0];  
  22.                         object para =values[1].ToString().Trim();  
  23.                         if (string.IsNullOrEmpty(values[1]))  
  24.                             para = tableSchema;  
  25.  
  26.                         dic.Add(values[0], para);  
  27.                     }  
  28.                 }  
  29.                 PropertyInfo[] pis = template.GetProperties();  
  30.                 foreach (PropertyInfo pi in pis)  
  31.                 {  
  32.                     object val=null;  
  33.                     if(dic.TryGetValue(pi.Name,out val))                      
  34.                       template.SetProperty(pi, val);  
  35.                 }     
  36.         
  37.                 if(File.Exists(targetFile))  
  38.                     File.Delete(targetFile);  
  39.                 using (StreamWriter writer = new StreamWriter(targetFile))  
  40.                 {  
  41.                     template.Render(writer);  
  42.                     writer.Flush();                      
  43.                 }  
  44.         }  

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

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

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

数据字典

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

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

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

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

  1. ddlCustomerGroup.InitializeValueListFromEnum(typeof(CustomeGroup)); 

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

  1. public static class DataBindingHelper  
  2.   {  
  3.       public static void InitializeValueListFromEnum(this ExtAspNet.DropDownList dropDownList, Type enumType)  
  4.       {  
  5.           dropDownList.Items.Clear();  
  6.           foreach (KeyValuePair<stringstring> item in StringEnum.GetValueStringList(enumType))  
  7.           {  
  8.               ExtAspNet.ListItem listitem = new ExtAspNet.ListItem(item.Value, item.Key);  
  9.               dropDownList.Items.Add(listitem);  
  10.           }  
  11.       }  

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

  1. public enum CustomeGroup  
  2. {  
  3.         [StringValue("Partner")]  
  4.         [DisplayText("Partner")]  
  5.         Partner,  
  6.  
  7.         [StringValue("Supplier")]  
  8.         [DisplayText("Supplier")]  
  9.         Supplier  

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

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

ExtAspNet控件扩展

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

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

  1. [Category(CategoryName.OPTIONS)]  
  2. [DefaultValue("")]  
  3. [Description("Data Binding")]  
  4. [Editor(typeof(QueryBindingTypeDialogEditor), typeof(UITypeEditor))]  
  5. public virtual string DataBindingString  
  6.         {  
  7.             get 
  8.             {  
  9.                 object obj = XState["DataBindingString"];  
  10.                 return obj != null ? obj.ToString() : "";  
  11.             }  
  12.             set 
  13.             {  
  14.                 XState["DataBindingString"] = value;  
  15.             }  
  16.     } 

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

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

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

  1. NODES.mainTabStrip.addTab({  
  2.        'id': tabID,  
  3.        'url': url,  
  4.        'title': title,  
  5.        'closable'true,  
  6.        listeners: {    
  7.                 'beforeclose': conrirmTab    
  8.            }  
  9.         }); 

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

  1. function conrirmTab(e) {  
  2.     Ext.MessageBox.show({  
  3.         title: 'Confirm',  
  4.         msg: 'Are you sure want to close  <b>' + e.title + '</b> ?',  
  5.         buttons: Ext.MessageBox.YESNO,  
  6.         icon: Ext.MessageBox.QUESTION,  
  7.         fn: function (btn, text) {  
  8.             if (btn == 'yes') {  
  9.                 NODES.mainTabStrip.remove(e);  
  10.             }  
  11.         }  
  12.     });  
  13.     return false;  

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

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

  1. //关闭活动的选项卡  
  2. function closeActivePanel() {  
  3.             var tabpanel = Ext.getCmp('<%= mainTabStrip.ClientID %>');  
  4.             var _activeTab = tabpanel.getActiveTab();  
  5.             if (_activeTab.x_iframe_url == "/Management/admin/default.aspx")  
  6.                 return;  
  7.             tabpanel.remove(_activeTab);  
  8. }  
  9.  
  10. //关闭所有选项卡  
  11. function closeAllPanel(){  
  12.             var tabpanel = Ext.getCmp('<%= mainTabStrip.ClientID %>');  
  13.             var _activeTab = undefined;  
  14.             for(var i=0;i< tabpanel.items.length;i++)  
  15.             {  
  16.                  _activeTab = tabpanel.items.items[i];  
  17.                  if (_activeTab.x_iframe_url!=undefined && _activeTab.x_iframe_url == "/Management/admin/default.aspx")  
  18.                     continue;  
  19.                  tabpanel.remove(_activeTab);  
  20.                  i = 0;  
  21.             }  
  22.             tabpanel.doLayout();  

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

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

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

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

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

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

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

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

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

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

  1. foreach (UserGroupMenuTypeEntity usermenuType in menu.UserGroupMenuTypes)  
  2. {  
  3.                 function c = LoadControl("function.ascx"as function;  
  4.                 c.LineBreakPlaceHolder.Text =GetTranslation(usermenuType.Description.Replace("&"""));  
  5.                 c.DataList1.DataSource = usermenuType.UserGroupMenuDetails;  
  6.                 c.DataList1.DataBind();  
  7.                 ph.Controls.Add(c);  
  8.  
  9.                 Literal liter = new Literal();  
  10.                 liter.Text = "<br />";  
  11.                 ph.Controls.Add(liter);  

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

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

原文链接:http://www.cnblogs.com/JamesLi2015/archive/2012/09/26/2703361.html

【编辑推荐】

  1. ASP.NET Web开发框架项目介绍
  2. ASP.NET Web开发框架之一 功能导航
  3. ASP.NET Web开发框架之二 数据输入窗体
  4. ASP.NET Web开发框架之三 报表开发
  5. ASP.NET Web开发框架之四 查询
  6. ASP.NET Web开发框架之六 数据库文档方法
  7. ASP.NET Web开发框架之七 开发流程与模式
责任编辑:张伟 来源: James Li的博客
相关推荐

2012-09-25 09:31:58

ASP.NETC#Web

2009-07-24 16:15:00

扩展ASP.NET G

2012-09-18 11:02:10

ASP.NETC#Web Forms

2012-10-08 14:01:54

ASP.NETWebC

2009-08-07 17:41:07

ASP.NET Web

2009-08-06 15:21:45

ASP.NET控件开发RenderConte

2009-08-04 10:43:59

ASP.NET控件开发

2012-09-20 09:54:12

ASP.NETWebC

2009-08-07 14:05:21

ASP.NET控件

2009-08-07 14:40:36

RegularExprASP.NET验证控件

2009-08-05 18:46:21

ComboBox显示ASP.NET控件开发

2012-09-29 13:20:30

ASP.NETWeb框架

2009-08-03 15:43:22

asp.net控件

2012-09-18 14:32:08

ASP.NETC#

2009-08-07 15:24:16

ASP.NET模板控件

2009-08-06 09:18:01

ASP.NET自定义控ASP.NET控件开发

2009-08-10 14:08:15

ASP.NET服务器控ASP.NET组件设计

2009-08-05 17:11:51

ASP.NET控件开发ASP.NET服务器控

2009-07-29 09:38:06

Web开发ASP.NET

2009-08-05 18:32:28

HtmlTextWriASP.NET控件开发
点赞
收藏

51CTO技术栈公众号