在开源之后,还没什么文章来说明 Discuz!NT项目的一些特点。作为这个控件库的设计者,本人将在接下来的时间里用连载的方式来向大家解释其中一些控件的设计思想,实现功能以及一些未曾使用过的功能展示(因为管理后台只使用控件的部分功能)。同时因为这组控件开发的周期很短(当时仅用一个半月,后不断增强功能),有不少思路和控件设计的规范相驳,但当时只考虑为后台程序开发和订制方便,因此就暂且开发成了这个样子,但本人日后会不断完善和规范这些代码:) 为了便于大家下载和使用这组控件,本人在源代码的基本上去掉了与项目相关的一些令人费解的的代码。同时把相关的控件与具体运行实例相绑定,这只是为了让大家使用和分析方便,必定不是库中所有控件大家都愿意用或感兴趣。正所谓投其所好嘛。另外下载包中的文件所在的项目和文件位置也是与开源项目中的配置相一致的,这么搞可以方便大家按图索骥,以便于同步开源项目中的文件。
同时,本人也希望园子里同行在使用和测试这组代码时将您的意见或建议提出来,以便改进和优化代码。还有就是这些控件代码是能在.net1.0 .net2.0框架上运行。欢迎大家使用:)
好了,今天就先说一下 Button 控件。
先贴一张运行效果图让大家看一下:
剖析 之 Button” src=”http://cdn.verydemo.com/upload/2013_06_08/13706427889380.jpg”>
开发动机:在去年10月底时,后台UI进行了一次重构,因为对.net 中的button控件和图片按钮控件感到控制不灵活(项目需要一个既有text 属性,又有img字段属性的按钮)。在看到了CS项目中所使用的按钮后,决定尝试实现与其类似的功能设计。另外因为当时设计部无法对我们直接进行支持,所以决定样式(css)直接采用cs中所使用的样式(偷个赖)。
实现功能:希望提供两种或以上的按钮样式,同时支持JS脚本注册,以及在客户端表单验证等。
因为要求做出多个显示样式,所以使用枚举方式显示可能选择的样式类型,相关代码如下:
1 properytyButtontypeMode 按钮样式#region properytyButtontypeMode 按钮样式2 public enum ButtonType3 {4 Normal, //普通5 WithImage, //带图6 XpStyle //不带图7 }8910 public ButtonType ButtontypeMode11 {12 get13 {14 object obj = ViewState[“ButtontypeMode”];15 return obj == null ? ButtonType.WithImage : (ButtonType)obj;16 }17 set18 {19 ViewState[“ButtontypeMode”] = value;20 }21 }22 #endregion2324
而脚本注册属性为string ,用于输入和保存相关脚本信息
1 [Description(“图版按钮链接”), DefaultValue(“../images/”)]2 public string ScriptContent3 {4 get5 {6 object obj = ViewState[“ScriptContent”];7 return obj == null ? “” : (string)obj;8 }9 set10 {11 ViewState[“ScriptContent”] = value;12 }13 }14是否支持客户端表单验证的属性如下:
1 定义是否调用js函数validate(this.form);进行数据校验#region 定义是否调用js函数validate(this.form);进行数据校验2 private bool _validateForm = false;3 //定义是否调用js函数validate(this.form);进行数据校验4 public bool ValidateForm5 {6 set7 {8 this._validateForm = value;9 }10 get11 {12 return this._validateForm;13 }14 }15 #endregion16
有了这几个属性,就可以在控件的Render函数中使用相关的设置了
1protected override void Render(HtmlTextWriter output)2 {3 //如果应用系统样式,这里只为当没有CSS文件时,则直接将样式写到控件中4 if (ApplyDefaultStyle)5 {6 if (this.ButtontypeMode == ButtonType.Normal)7 {8 output.Write(“<span><a href=”javascript:void(0);” >9 #999999 1px solid; PADDING-RIGHT: 10px; BACKGROUND-POSITION: 1px 1px; BORDER-TOP:10 #cccccc 1px solid; DISPLAY: inline-block; PADDING-LEFT: 10px; FONT-WEIGHT: bold;11 12 }1314 if (this.ButtontypeMode == ButtonType.WithImage)15 {16 output.Write(“<span><a href=”javascript:void(0);” >17 PADDING-RIGHT: 3px; BACKGROUND-POSITION: 1px 1px; BORDER-TOP: #cccccc 1px solid;18 DISPLAY: inline-block; PADDING-LEFT: 22px; FONT-WEIGHT: bold; FONT-SIZE: 12px;19 PADDING-BOTTOM: 3px; MARGIN: 1px; BORDER-LEFT: #cccccc 1px solid; CURSOR: pointer;20 21 }2223 if (this.ButtontypeMode == ButtonType.XpStyle)24 {25 output.Write(“<span >26 display: -moz-inline-box; PADDING-LEFT: 4px; FONT-WEIGHT: bold; FONT-SIZE: 12px;27 BACKGROUND-IMAGE: url(” + this.XpBGImgFilePath + “/xpbuttonbg_l.gif);28 29 }30 }31 3233 //表单验证属性判断,(注:要在web页面上FORM的submit中加入该函数,并进行相关声明34 //即可,参见webtest页面)35 if (ValidateForm)36 {37 sb.Append(“if(validate(this.form)){“);38 //当验证通过后则执行向服务器提交内容的JS代码39 sb.Append(Page.GetPostBackEventReference(this,””) + “;}”);40 4142 //用户希望进行注册的JS代码,这块代码可放在表单验证属性判断之前。43 if (ScriptContent != “”)44 {45 sb.Append(ScriptContent);46 }4748 //将上来的设置写入到客户端的onlick事件中。49 output.WriteAttribute(“onclick”, sb.ToString());50 }51525354现在可以说从服务器端设置到客户端脚本生成基本上都开发完了。
接下来是做服务器端事件的绑定处理,
1 protected static readonly object EventClick = new object();23 public event EventHandler Click4 {5 add6 {7 Events.AddHandler(EventClick, value);8 }9 remove10 {11 Events.RemoveHandler(EventClick, value);12 }13 }1415 protected virtual void OnClick(EventArgs e)16 {17 EventHandler clickHandler = (EventHandler)Events[EventClick];18 if (clickHandler != null)19 {20 clickHandler(this, e);21 }22 }232425 public void RaisePostBackEvent(string eventArgument)26 {27 OnClick(new EventArgs());28 }293031 void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)32 {33 this.RaisePostBackEvent(eventArgument);34 }3536
这样就完成了这个控件的主干部分,而其它的一些属性,如图片路径之类的代码大家可参见一下源码,这里就不多做说明了。
未来实现的功能,应该说主要还是在UI表现上,希望能让用户的接受起来更快,色调也更加柔和等等……
本文作者:用最少的浪费面对现在