使用 WebCustomControls 的 UpdownNumeric、IP、Timer 和 Validated TextBox 控件





3.00/5 (1投票)
2006年7月10日
5分钟阅读

33987

647
下载 EuroNetWebCustomControls 套件演示项目 - 26.3kb 和源代码 - 31 kb。此自定义控件套件包含 UpdownNumerci、IP、Timer 和 Validated Text Box 控件。我使用 .Net2003 中的 WebCustomContolsLibrary 创建了这些控件。
引言
我目前的工作涉及将我们部分 Windows 应用程序迁移到 Web 应用程序。我们的 Win 应用中有类似的控件(IP 控件、Numeric 控件和 Timer 控件)。Visual Studio 中的默认 Web 控件不提供上述功能。那时我决定自己编写一些控件。总共有 4 个控件,如下所述:
Validated Textbox - 此控件公开一个名为 NotAllowedChars 的属性。在此属性中指定您不希望控件接受的字符。请注意,如果您需要避免使用双引号("),则应仅按以下格式输入 - "。还有一个 Width 属性,方便开发人员为文本框提供宽度。
UpdownNumeric - 此控件包含一个文本框和两个按钮。有 2 个属性:Min 和 Max,用于设置文本框中输入值的范围。值可直接在文本框中输入。或者,可以通过提供的按钮来增加/减少值。只需单击按钮一次即可增加/减少值,或者将鼠标按住按钮即可自动增加/减少。
我已为按钮设置了默认图像。如果您想使用自己的图像,可以通过设置 UpImage 和 DownImage 属性来实现。
Timer Control - 我在这个计时器控件中组合了两个不同的控件。我提供了一个名为 Type 的属性,它是 Enum 类型。默认值为 HourMin。在这种情况下,您可以看到两个文本框和两个按钮。第一个文本框只接受小时(24 小时制)。第二个文本框接受分钟。
如果将 Type 属性更改为 HourMinSec,您将看到用于秒的第三个文本框。按钮操作与上述控件相同。默认情况下,我已设置按钮图像。如果您想更改这些图像,可以通过 UpImage 和 DownImage 属性进行设置。
IP Control - 此控件接受 IP 地址,包含 4 个由连字符 (-) 分隔的文本框。
注意
每个控件都具有以下属性:
1. ClientSideScriptLocation。您应该在此处指定 Javascript (Euronet.NetWebControlsValidation.js) 文件的位置。
2. EuroNetCss。指定 CSS 类名。
Validated Textbox 的代码说明
false),Category("Appearance"),DefaultValue("")>
public string Text
{
get {return text; }
set {text = value;}
}
false),Category("Appearance"),DefaultValue("")>
public string NotAllowedChar
{
set {hNotAllowedChar = value;}
get{return hNotAllowedChar;}
}
我的控件的 Text 属性 与 asp.net Textbox 控件的 Text 属性相同。无需进一步解释。下一个 NotAllowedChar 属性 是我的特殊属性。在此属性中指定您不希望控件接受的字符。我遇到一个小问题 - 双引号内的字符未得到验证。为了解决这个问题,我使用了一个隐藏的 Textbox 来维护 NotAllowedCharacters。我将此隐藏 Textbox 的值传递给脚本。双引号("")内的字符将被视为已验证字符串。
唯一的条件是,如果您输入双引号("),它将无法正常工作。但我已经提供了解决方法。请看下面的代码。
protected override void Render(HtmlTextWriter output)
{
output.WriteBeginTag("EuroControls");
output.Write("\n<input type=hidden id="+ID+
"_hidNotAllowedCharCode Value=\""+NotAllowedChar+"\">");
output.Write("\n<script language="'javascript'" src='"+
sScriptLocation+"'></script>");
if(Enabled)
output.Write("\n<input type=text name="+this.UniqueID+" id="+
this.UniqueID+" onkeypress=keyRestrict(event,'"+
ID+"') Value='"+Text+"' style='"+EuronetStyle+
"' class='"+CssClass+"' runat="server">");
else
output.Write("\n<input type=text readOnly name="+this.UniqueID+
" id="+this.UniqueID+" onkeypress=keyRestrict(event,'"+
ID+"') Value='"+Text+"' style='"+
EuronetStyle+"color:gray;' class='"+CssClass+
"' runat="server">");
}
您还可以设置 Enabled 和 Disabled 属性。在我们的页面生命周期场景中,当控件处于禁用模式时,控件的值不会保留。
因此,我没有禁用控件。而是设置了控件的只读属性,并更改了颜色使其看起来像禁用模式。
注意:此属性对所有控件都是通用的。
我继承了 IPostBackDataHandler 以便保留 Postback 数据。请看下面的代码。
public bool LoadPostData(String postDataKey, NameValueCollection values)
{
Text = values[this.UniqueID];
return false;
}
IP Control 的代码说明
IP 控件总共包含 7 个 HtmlInputTextBox 控件 - 四个用于用户输入,其余用作分隔符。
在此控件中,我继承了 INamingContainer 接口,为每个控件创建唯一的 ID。
以下代码显示了控件是如何创建的。我重写了 CreateChildControls 方法来创建控件。
protected override void CreateChildControls()
{
ctlIpText1 = new System.Web.UI.HtmlControls.HtmlInputText();
ctlIpText1.ID = "txtIP1";
ctlIpText1.Attributes.Add("runat","Server");
ctlIpText1.Attributes.Add("onkeypress","IsNumeric(event)");
ctlIpText1.Attributes.Add("onfocus", "SelText('"+this.UniqueID+"_txtIP1')");
ctlIpText1.Attributes.Add("tabIndex",(base.TabIndex+1).ToString());
ctlIpText1.Attributes.Add("onblur",
"ValidateIP('"+this.UniqueID+"','txtIP1')");
ctlIpText1.MaxLength = 3;
ctlIpText2 = new System.Web.UI.HtmlControls.HtmlInputText();
ctlIpText2.ID = "txtIP2";
ctlIpText2.Attributes.Add("runat","Server");
ctlIpText2.Attributes.Add("onkeypress","IsNumeric(event)");
ctlIpText2.Attributes.Add("onfocus", "SelText('"+this.UniqueID+"_txtIP2')");
ctlIpText2.Attributes.Add("tabIndex",(base.TabIndex+2).ToString());
ctlIpText2.Attributes.Add("onblur", ValidateIP('"+
this.UniqueID+"','txtIP2')");
ctlIpText2.MaxLength = 3;
ctlIpText3 = new System.Web.UI.HtmlControls.HtmlInputText();
ctlIpText3.ID = "txtIP3";
ctlIpText3.Attributes.Add("runat","Server");
ctlIpText3.Attributes.Add("onkeypress","IsNumeric(event)");
ctlIpText3.Attributes.Add("onfocus", "SelText('"+this.UniqueID+"_txtIP3')");
ctlIpText3.Attributes.Add("tabIndex",(base.TabIndex+3).ToString());
ctlIpText3.Attributes.Add("onblur", "ValidateIP('"+this.UniqueID+"','txtIP3')");
ctlIpText3.MaxLength = 3;
ctlIpText4 = new System.Web.UI.HtmlControls.HtmlInputText();
ctlIpText4.ID = "txtIP4";
ctlIpText4.Attributes.Add("runat","Server");
ctlIpText4.Attributes.Add("onkeypress","IsNumeric(event)");
ctlIpText4.Attributes.Add("onfocus", "SelText('"+this.UniqueID+"_txtIP4')");
ctlIpText4.Attributes.Add("tabIndex", (base.TabIndex+4).ToString());
ctlIpText4.Attributes.Add("onblur", "ValidateIP('"+
this.UniqueID+"','txtIP4')");
ctlIpText4.MaxLength = 3;
ctlIpText1.Value = SplitIp(Text, 0);
ctlIpText2.Value = SplitIp(Text, 1);
ctlIpText3.Value = SplitIp(Text, 2);
ctlIpText4.Value = SplitIp(Text, 3);
ctlHyText1 = new System.Web.UI.HtmlControls.HtmlInputText();
ctlHyText1.ID = "txtHy1";
ctlHyText1.Value = "-";
ctlHyText1.Attributes.Add("tabIndex","5");
ctlHyText1.Attributes.Add("readOnly","true");
ctlHyText2 = new ystem.Web.UI.HtmlControls.HtmlInputText();
ctlHyText2.ID = "txtHy2";
ctlHyText2.Value = "-";
ctlHyText2.Attributes.Add("tabIndex","6");
ctlHyText2.Attributes.Add("readOnly","true");
ctlHyText3 = new System.Web.UI.HtmlControls.HtmlInputText();
ctlHyText3.ID = "txtHy3";
ctlHyText3.Value = "-";
ctlHyText3.Attributes.Add("tabIndex","7");
ctlHyText3.Attributes.Add("readOnly","true");
ctlTable = new System.Web.UI.HtmlControls.HtmlTable();
ctlTable.Attributes.Add("style","BORDER-RIGHT: gray 0px solid; " +
"BORDER-TOP: gray 0px solid; BORDER-LEFT: " +
"gray 0px solid; BORDER-BOTTOM: gray 0px solid");
ctlRow = new System.Web.UI.HtmlControls.HtmlTableRow();
ctlRow.Attributes.Add("style", "BORDER-RIGHT: gray 0px solid; " +
"BORDER-TOP: gray 0px solid; BORDER-LEFT: " +
"gray 0px solid; BORDER-BOTTOM: gray 0px solid");
ctlTable.Rows.Add(ctlRow);
ctlCell = new System.Web.UI.HtmlControls.HtmlTableCell();
ctlCell.Attributes.Add("style","BORDER-RIGHT: gray 0px solid; " +
"BORDER-TOP: gray 0px solid; BORDER-LEFT: " +
"gray 0px solid; BORDER-BOTTOM: gray 0px solid");
ctlCell.Controls.Add(ctlIpText1);
ctlCell.Controls.Add(ctlHyText1);
ctlCell.Controls.Add(ctlIpText2);
ctlCell.Controls.Add(ctlHyText2);
ctlCell.Controls.Add(ctlIpText3);
ctlCell.Controls.Add(ctlHyText3);
ctlCell.Controls.Add(ctlIpText4);
ctlRow.Cells.Add(ctlCell);
this.Controls.Add(ctlTable);
}
以下属性用于获取和设置 IP 地址。
false), Category("Data"), DefaultValue("0"),
Description("The Text for Numeric TextBox")>
public string Text
{
get
{
this.EnsureChildControls();
return ctlIpText1.Value+"-"+ ctlIpText2.Value+"-"+
ctlIpText3.Value+"-"+ctlIpText4.Value;
}
set
{
this.EnsureChildControls();
string[] strarrIp = value.Split(new char[] {'-'});
if(strarrIp != null)
{
ctlIpText1.Value = strarrIp[0];
ctlIpText2.Value = strarrIp[1];
ctlIpText3.Value = strarrIp[2];
ctlIpText4.Value = strarrIp[3];
}
else
{
ctlIpText1.Value = "";
ctlIpText2.Value = "";
ctlIpText3.Value = "";
ctlIpText4.Value = "";
}
}
}
EnsureChildControls 方法确保当前控件拥有子控件。然后,它获取或设置当前控件的 ControlCollection 对象中子 Textbox 控件的 Text 属性。
Timer Control 的代码说明
为了构建此控件,我使用了三个 HtmlInputTextbox 和两个 HtmlButton 控件。我为开发人员提供了从 HourMinSec Timer 切换到 HourMin 以及反之亦然的选项。在此控件中,我使用了与上述控件相同的技术。
但我增加了一些额外功能,即UpDown 按钮的默认图像。因此,开发人员可以更改此属性来设置自己的图像。
我使用一个类来从属性窗口打开文件对话框。请看下面的代码。
public class UrlImageEditor: System.Web.UI.Design.UrlEditor
{
protected override string Caption
{
get
{
return "Select Image";
}
}
protected override string Filter
{
get
{
return "ImageFiles(*.gif,*.jpg,*.jpeg,*.bmp,*.wmf," +
"*.png) |*.gif;*.jpg;*.jpeg;*.bmp;*.wmf;*.png|All Files(*.*)|*.*";
}
}
}
public class UrlFileEditor: System.Web.UI.Design.UrlEditor
{
protected override string Caption
{
get
{
return "Select File";
}
}
protected override string Filter
{
get
{
return "ScriptFile(*.js)|*.*";
}
}
}
我将上述类写在一个单独的类文件中(易于理解)。以下属性显示了我如何使用这些类。
[Category("Appearance"),Bindable(false),
Description("Image to use if the down button is an image"),
DefaultValue(""), Browsable(true),
EditorAttribute(typeof(cEditor.UrlImageEditor),
typeof(System.Drawing.Design.UITypeEditor))]
public string ImageUp
{
set
{
this.EnsureChildControls();
ctlButtonUp.Src = value;
sUpImagePath = value;
}
get
{
return sUpImagePath ;
}
}
EditorAttribute 在属性窗口中放置了一个按钮。此按钮会启动文件对话框。我对选择 ClientSideScriptLocatin 属性也做了同样的处理。
这里也有一个问题 - 当我从默认值切换控件时,出现了一些设计问题和脚本错误。这是因为当您更改控件类型属性时,CreateChildControls 方法没有被触发。
因此,我显式地清除所有控件,并在更改控件类型时重新创建控件。请看下面的属性。
false), Category("Behavior"),
DefaultValue("ControlType.HourMinTimer"),
Description("Control Type")>
public ControlType Type
{
set
{
_Type = value;
this.Controls.Clear();
CreateChildControls();
Text = "00:00:00";
if(Directory.Exists(path+"/EuroNetWebControlsImages"))
{
ImageUp = path+"/EuroNetWebControlsImages/up.bmp";
ImageDown = path+"/EuroNetWebControlsImages/down.bmp";
}
else
{
ImageUp = ImageUp;
ImageDown = ImageDown;
}
}
get
{
return _Type;
}
}
以下代码显示了如何为按钮设置默认图像。当您将控件拖放到表单上时,我会在您的应用程序路径中创建一个 Image 文件夹,并将图像放在该文件夹中。但在此之前,您的应用程序文件夹应具有写入权限。否则,将无法创建默认图像。
private void LoadDefaultImage()
{
try
{
path = GetAppFolder();
if(!Directory.Exists(path+"/EuroNetWebControlsImages"))
{
Directory.CreateDirectory(path+"/EuroNetWebControlsImages");
}
System.IO.Stream sr;
byte[] by;
System.IO.MemoryStream ms;
System.Drawing.Bitmap bm;
if(!File.Exists(path+"/EuroNetWebControlsImages/up.ico"))
{
sr = System.Reflection.Assembly.LoadWithPartialName(
"EuroNetWebControls").GetManifestResourceStream(
"EuroNetWebControls.Images.up.bmp");
by = new byte[sr.Length];
sr.Read(by, 0, (int)sr.Length);
ms = new System.IO.MemoryStream();
ms.Write(by, 0, by.Length);
bm = new Bitmap(ms);
bm.Save(path+"/EuroNetWebControlsImages/up.bmp");
ImageUp = path+"/EuroNetWebControlsImages/up.bmp";
ms.Close();
}
else
{
ImageUp = path+"/EuroNetWebControlsImages/up.bmp";
}
if(!File.Exists(path+"/EuroNetWebControlsImages/down.ico"))
{
sr = System.Reflection.Assembly.LoadWithPartialName(
"EuroNetWebControls").GetManifestResourceStream(
"EuroNetWebControls.Images.down.bmp");
by = new byte[sr.Length];
sr.Read(by, 0, (int)sr.Length);
ms = new System.IO.MemoryStream();
ms.Write(by, 0, by.Length);
bm = new Bitmap(ms);
bm.Save(path+"/EuroNetWebControlsImages/down.bmp");
ImageDown = path+"/EuroNetWebControlsImages/down.bmp";
ms.Close();
}
else
{
ImageDown = path+"/EuroNetWebControlsImages/down.bmp";
}
}
catch{}
}
private string GetAppFolder()
{
try
{
string path = Assembly.GetExecutingAssembly().CodeBase;
path = path.Remove(0,8);
path = path.Replace("/","\\");
path = path.Substring(0,path.LastIndexOf("\\",path.Length,
path.Length - 1));
return path.Substring(0,path.LastIndexOf("\\",path.Length,
path.Length - 1));
}
catch(Exception)
{ return null; }
}
UpDownNumeric Control 的代码说明
此控件的功能与我在 Timer 控件中所做的类似。
在此控件中,我添加了两个属性 Max 和 Min。开发人员可以设置最大和最小值。利用此属性,开发人员可以限制用户的取值范围。
其他所有内容都与 Timer 控件相同。
false), Category("Misc"), DefaultValue("0"),
Description("To set the Minimum value of Numeric Textbox")>
public string Min
{
get
{
this.EnsureChildControls();
return ctlHidMin.Value;
}
set
{
this.EnsureChildControls();
ctlHidMin.Value = value;
Text = value;
}
}
false), Category("Misc"), DefaultValue("100"),
Description("To set the Maximum value of Numeric Textbox")>
public string Max
{
get
{
this.EnsureChildControls();
return ctlHidMax.Value;
}
set
{
this.EnsureChildControls();
ctlHidMax.Value = value;
}
}
我将我的 JavaScript 与本文一起发布。该脚本非常容易理解,无需任何解释。
关注点
我曾试图通过属性窗口显示样式生成器。目前我无法做到。我到处搜索过。但没有找到。如果您有任何关于增强控件以及如何整合样式生成器的想法,请发表。
这对我和其他需要相同功能的开发人员都非常有帮助。