WEB自定义控件小记
以前我在做项目的时候,都是用的是用户自定义控件,这一回我看了一下自定义控件。
它们两者的不同点在于:用户自定义控件是基于横向的,也就是说可以用多个控件组合在一起使用;而自定义控件是纵向的,是一个已存在控件的扩展。
新建一个WEB自定义控件项目;
由于在项目中经常会用到点一个BUTTON的时候,要弹出JS的确认对话框,第一次都要在页面上加入JS,很麻烦,这个过程是可以封装的~~
新建一个“自定义控件”,取了个名字:MyButton,这时会发现这个类是继承自WebControl的,把它改成Button,也就是说只扩展BUTTON,把类中的所有代码删掉,新建一个属性,Confirm,也就是在弹出对话框时,要显示的内容。
重写Render方法,代码如下:
base.Attributes.Add("onclick", "return confirm('" + this.confirm + "')");
base.Render(writer);
(注:Render是控件的表现方法,如果想让自定义控件表现成指定的样式,那么就得继承WebControl类,在重写的Render方法中,writer.Write(),这里输入自己想要的HTML控件就可以了。)
就这样,一个简单的控件就完成了,编译,新建一个网站,在工具箱中加入这个DLL,拖出来,运行这个页面,会发现,点击这个BUTTON的时候,发弹出一个提示框,当然,默认的情况下是空的,是因为没有设置Confirm这个属性,设个字符就可以了。
但是,认真看一下,为什么这个属性在使用的时候没有注释呢,于是马上把注释写好,编译之后发现,还是没有,怎么回事呢。
经查找,原来自定义控件是不能这样直接写注释的,要想加入注释,得加一个特性标签,Description,Category标签是表示当属性用分类形式查看的时候,这个属性显示在那个分类里面,完整代码如下:
[DefaultProperty("Text")]
[ToolboxData("<{0}:MyButton runat=server></{0}:MyButton>")]
public class MyButton : Button
{
private string confirm = "是否确定?";
[Description("确定对话框的内容"), Category("必设属性")]
public string Confirm
{
get { return confirm; }
set { confirm = value; }
}
protected override void Render(HtmlTextWriter writer)
{
base.Attributes.Add("onclick", "return confirm('" + this.confirm + "')");
base.Render(writer);
}
}
用同样的原理做了一个LinkButton的控件,代码都一样,只不过所继承的是LinkButton这个类而已。
最后我还做了一个TextBox的控件,这个也是很常用的,因为在很多时候要限定只能输入数字之类的,最终我把它做成了一个可设定很多选项的控件,
如:是否允许粘贴,是否允许拖动,是否允许输入小数点,小数点之后保留多少位,是否允许切换为其它输入法,有了这几个属性之后,相信很多地方都可以直接用啦~~
代码如下:
[ToolboxData("<{0}:MyTextBox runat=server></{0}:MyTextBox>")]
public class MyTextBox : TextBox
{
protected override void Render(HtmlTextWriter writer)
{
if (this.allowPaste == AllowType.不允许)
{
base.Attributes.Add("onpaste", "return false");//禁止粘贴
}
else
{
base.Attributes.Add("onpaste", @"var s=clipboardData.getData('text'); if(!/\D/.test(s)) value=s.replace(/^0*/,''); return false;");
}
if (this.allowMove == AllowType.不允许)
{
base.Attributes.Add("ondragenter", "return false");//禁止拖动
}
base.Attributes.Add("onkeyup", "if(value.length>1)value=value.replace(/^0*/, '');");//开头的0替换为空
base.Attributes.Add("onfocus", " var e = event.srcElement; var r =e.createTextRange(); r.moveStart('character',e.value.length); r.collapse(true); r.select(); ");
if (allowPoint == AllowType.不允许)
{
base.Attributes.Add("onkeypress", "return event.keyCode>=48&&event.keyCode<=57");//只能输入数字
}
else
{
base.Attributes.Add("onkeypress", "var index=value.indexOf('.');var len=index+" + this.behindPoint + "; if(index!=-1&&value.length>len){return false;} if((index==-1&&event.keyCode==46)||(event.keyCode>=48&&event.keyCode<=57)){return true;}else{return false;}");//只能输入 数字 和 一次小数点
base.Attributes.Add("onblur", " var index=value.indexOf('.'); if(index==0)value=value.replace('.', '0.'); ");//开头的小数点换为 "0."
}
if (allowInputMethod == AllowType.不允许)
{
base.Style.Add("ime-mode", "disabled");//禁用输入法
}
base.Render(writer);
}
private AllowType allowPaste = AllowType.不允许;
[Description("是否允许粘贴,默认不允许"), Category("可选属性")]
public AllowType AllowPaste
{
get { return allowPaste; }
set { allowPaste = value; }
}
private AllowType allowMove = AllowType.不允许;
[Description("是否允许拖动,默认不允许"), Category("可选属性")]
public AllowType AllowMove
{
get { return allowMove; }
set { allowMove = value; }
}
private AllowType allowPoint = AllowType.不允许;
[Description("是否允许输入小数点,默认不允许"), Category("可选属性")]
public AllowType AllowPoint
{
get { return allowPoint; }
set { allowPoint = value; }
}
private int behindPoint = 2;
[Description("小数点之后保留多少位,在允许小数点的情况下可用,默认 2位"), Category("可选属性")]
public int BehindPoint
{
get { return behindPoint; }
set { behindPoint = value; }
}
private AllowType allowInputMethod = AllowType.不允许;
[Description("是否允许切换为其它输入法,默认不允许"), Category("可选属性")]
public AllowType AllowInputMethod
{
get { return allowInputMethod; }
set { allowInputMethod = value; }
}
}
public enum AllowType
{
允许,
不允许,
}
这里加入了一个枚举,主要是为是在用户使用控件的时候不用输入,而是直接选择,比较方便。
最后这个自定义控件前前后后地我改了很多地方,我觉得还是非常满意了。