如有不明白的地方欢迎加QQ群14670545 探讨
这一节先来个简单的text,下一节是button,然后我们把这三节串联起来。
接着上面的,我们在CustomerWebControls类库(可不是内裤哦)中新增一个类,就叫CCJonText.cs 。因为是textbox,所以这个类我们需要让它继承
System.Web.UI.WebControls.TextBox具体代码如下:
public class CCJonText : System.Web.UI.WebControls.TextBox { /// <summary> /// 重写OnPreRender事件 /// <remarks>OnPreRender:在客户端上呈现之前注册用于生成回发事件的客户端脚本</remarks> /// </summary> protected override void OnPreRender(EventArgs e) { if (string.IsNullOrEmpty(CssClass)) { base.Attributes.Add("onfocus", "this.className='text_field_on';");//获取焦点时的样式 base.Attributes.Add("onblur", "this.className='text_field';");//失去焦点时的样式 base.CssClass = "text_field"; } base.OnPreRender(e); } protected override void Render(System.Web.UI.HtmlTextWriter writer) { base.Render(writer); } }
[System.Web.UI.ToolboxData("<{0}:CCJonText runat=server></{0}:CCJonText>")] [System.ComponentModel.Designer("System.Web.UI.Design.WebControls.PreviewControlDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public class CCJonText : System.Web.UI.WebControls.TextBox ......
一个一个来说,ToolboxData是定义我们这个当前写的控件 从工具箱拖动到页面时为它生成的默认标记,下面会看到效果;
Designer是为说明当前这个textbox(CCJonText是继承于System.Web.UI.WebControls.TextBox的,所以它也是textbox哦)由哪个类指定生成的,这里有版本描述的,我用的是vs2010 fm4.0搭建的demo,所以这里应该用4.0的生成描述,如果我们不知道怎么写,那么可以把鼠标放到System.Web.UI.WebControls.TextBox的TextBox上,然后F12进去,看到最顶部的Designer了吧,把那段复制下就OK了。同理如果是2.0的会是这个样子的:
System.Web.UI.Design.WebControls.PreviewControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
不扯远了,其它版本自己试验,接着看下面的
添加属性:为控件添加属性主要是通过基类的Attributes方法,看到上的base.Attributes.Add(....了吧,这里base是执行最近一个基类的方法,不说了。下面我们为这个CCJonText添加属性;
先写一个方法
/// <summary> /// 添加属性方法 /// </summary> /// <param name="key">键值,如class等</param> /// <param name="valuestr">要绑定的字符串</param> public void AddAttributes(string key, string valuestr) { this.Attributes.Add(key, valuestr); }然后我们限定这个textbox(CCJonText)的的输入字符长度
/// <summary> /// 控件的最大长度属性 /// </summary> [System.ComponentModel.Bindable(true)]//在属性窗口中是否可见 [System.ComponentModel.Category("Appearance")]//属性的分类,如,行为,外观,大家可以在属性窗口看见这样的分类 [System.ComponentModel.DefaultValue("")]//默认值 [System.ComponentModel.Localizable(true)]//这些是显示在属性窗口底下的 public override int MaxLength { get { object o = ViewState["CCJonText_MaxLength"]; if (o != null) { int maxlength = tools.StrToInt(o.ToString(), 6);//默认让它最长输入字符6位 AddAttributes("maxlength", maxlength.ToString()); return maxlength; } else { return -1; } } set { ViewState["CCJonText_MaxLength"] = value; AddAttributes("maxlength", value.ToString()); } }
StrToInt只是我的库中的一个自定义函数,把对象转成int型,这个网上大把的,自己找找,不贴了。
这里要说一下,为什么要放viewstate呢,这个要理解它了,它以名值对的方式来存控件的值,和Hashtable的结构有些类似,最重要的是在页面回传的过程中记住所有状态值。
下面我们再来重写下Text属性,因为很多时候我们需要限制输入什么,因为时间仓促,这里处理的比较仓促了,我没有封装js进来,等下个例子我会补上去。先看下面;
/// <summary> /// 输入框内容 /// </summary> public override string Text { get { return base.Text.Trim(); } set { base.Text = value; } }这算的上是TextBox的Text的原型了。下面我们变动一下,假如我们的这个CCJonText在页面渲染之后呈现出来或者向服务器提交数据的时候有特殊字符怎么办,当然,我们在web层后台可以很好处理的,但这里我们可以做一些简单的封装处理,比如,给这个textbox(我们的CCJonText)加上是否过滤特殊关键词,好的,看下面代码:
/// <summary> /// 是否移除不安全字符串 /// </summary> [System.ComponentModel.Bindable(true)]//在属性窗口中是否可见 [System.ComponentModel.Category("Appearance")]//属性的分类,如,行为,外观,大家可以在属性窗口看见这样的分类 [System.ComponentModel.DefaultValue(true)]//默认值 [System.ComponentModel.Localizable(true)]//这些是显示在属性窗口底下的 public bool IsRemoveUnsafeHtml { set { ViewState["IsRemoveUnsafeHtml"] = value; } get { return ViewState["IsRemoveUnsafeHtml"] != null ? (bool)ViewState["IsRemoveUnsafeHtml"] : true; } }
/// <summary> /// 输入框内容 /// </summary> public override string Text { get { return IsRemoveUnsafeHtml ? tools.RemoveUnsafeHtml(base.Text.Trim(), 1) : base.Text.Trim(); } set { base.Text = value; } }
这里RemoveUnsafeHtml一个函数,处理特殊字符的,比如我们可以这样去写:
public class tools { private const string StrKeyWord = @"select|insert|delete|from|drop table|update|truncate|xp_cmdshell|exec master|netlocalgroup administrators|:|net user"; public static string RemoveUnsafeHtml(string content, int tag = 1) { content = content.Replace("'", "").Replace("%", "").ToLower(); string[] arry_sql = StrKeyWord.Split('|'); foreach (string paramSQL in arry_sql) if (content.IndexOf(paramSQL) > -1) content = content.Replace(paramSQL, "$$"); return content; } .......上面随便写的,我写的比较死哦,要是乐意自己去敲,可以把StrKeyWord写到配置文件里面,总字不要写死好了。
好了下面重新编译一下CustomerWebControls,然后我们把web层清理下,重新生成。打开一个页面,切换到设计或者源状态,再把工具箱打开,是不是看到2个自定义的控件了呢,其中一个是我们上一节测试的demo,,我们把CCJonText拖一个到页面上去看看,这个时候页面会自动添加2行代码,头部和呈现的部分:
<%@ Register Assembly="CustomerWebControls" Namespace="CustomerWebControls" TagPrefix="cc1" %>
<cc1:CCJonText ID="CCJonText3" runat="server"></cc1:CCJonText>
现在我们就可以给它添加刚刚我们写的属性了,<cc1:CCJonText ID="CCJonText1" runat="server" IsRemoveUnsafeHtml="true" MaxLength="8"></cc1:CCJonText>
大家可以测下输入那些特殊字符,服务端是怎么处理的,断点进去很好测,这就不说了。下节我们把js封装进来,会更加丰富。先到这,下班