使用自定义 HTML 属性扩展 ASP.NET Web 控件






4.83/5 (32投票s)
2005年4月13日
4分钟阅读

239701

2093
利用 ASP.NET 的现有功能来扩展框架的 Web 控件。
引言
您是否曾编写代码为现有的 ASP.NET 控件实现自定义功能(文本格式化、权限检查等)? 您可以通过实现自定义 Web 控件来实现这些定制,但是,如果能为现有的 ASP.NET 控件应用额外的属性来实现相同的结果,那岂不是更好? 本文将介绍一种利用 ASP.NET 的现有功能,通过应用自己的自定义 HTML 属性来扩展现有 Web 控件的方法。
快速背景介绍
要理解此扩展功能,必须熟悉 ASP.NET 的生命周期,特别是 System.Web.UI.Page
创建其子控件的方式。 如果查看 Page
的对象层次结构,您会发现它直接继承自 System.Web.UI.TemplateControl
,而后者又继承自 System.Web.UI.Control
。 Control
类定义了受保护的虚拟方法 CreateChildControls
,该方法用于通知服务器控件创建任何包含的子控件,为回发或呈现做准备。 要实现此方法的我们自己的版本,我们需要创建继承自 System.Web.UI.Page
的自己的类。
创建一个简单的自定义页面
要实现一个简单的 ASP.NET 基类页面,请定义一个继承自 System.Web.UI.Page 的新类。
public class BasePage : System.Web.UI.Page { ... }
接下来,我们需要重写 CreateChildControls
方法来指定我们自己的控件创建逻辑。
protected override void CreateChildControls() { ... }
由于所有 Web 控件和用户控件都必须位于 HTML 表单中才能工作,因此我们需要做两件事:
- 在
CreateChildControls
中,遍历所有“页面”控件,并找到类型为System.Web.UI.HtmlControls.HtmlForm
的控件。 - 遍历表单控件内的控件,并选择所有类型为
System.Web.UI.WebControls.WebControl
的控件。
以下代码定义了此发现过程:
/// <summary> /// Overrides the common functionality for the creation /// of controls within the page. /// </summary> protected override void CreateChildControls() { // Find the form control in which all asp.net (or custom) controls // must be hosted. foreach (Control c in this.Controls) { if (c is System.Web.UI.HtmlControls.HtmlForm) { ProcessForm(c as HtmlForm); } } // Call the base implementation base.CreateChildControls(); } /// <summary> /// Process each of the controls within the form /// </summary> /// <param name="form">The html form for the page</param> private void ProcessForm(HtmlForm form) { // Find all the web controls, ie <asp:control_name />, and // check process them. // // You can also add logic here to check for user controls or // custom user controls. foreach (Control cc in form.Controls) { if (cc is WebControl) { // Once you find the a web control, process any // custom attributes you have specified. AttributeParser.ProcessControl(cc as WebControl); } } }
现在我们有了基类页面并定义了发现过程,我们可以借助一些额外的类来开始处理我们的自定义属性。
代码逐步解析
用于发现自定义 HTML 属性的主要类是 AttributeParser
类。 此类包含一个名为 ProcessWebControl
的方法,该方法简单地遍历所有先前定义的属性(由 AttributeType
枚举表示),并检查每个 Web 控件的属性是否匹配。 如果找到匹配项,则 AttributeType
将与 AttributeFactory
类结合使用,以获取实现 IAttribute
接口的类的实例。 使用此类的实例,我们然后调用 IAttribute.Apply
方法,并将属性的值连同定义该属性的控件一起传递。 这将允许实现类根据自定义 HTML 属性的值对 Web 控件执行任何自定义操作。
以下是代码的快速预览:
/// <summary> /// Processes the control's custom attributes. /// </summary> /// <param name="control">Current web control being rendered.</param> public static void ProcessControl(WebControl control) { foreach(string attribute in Attributes) { // Get the value of the custom attributes string attributeValue = control.Attributes[attribute]; // If the custom attribute is defined, process it if (attributeValue != null) { // Get the attribute's type AttributeType at = (AttributeType)Enum.Parse(typeof(AttributeType), attribute, true); // Get the class to process the custom attribute IAttribute customAttribute = AttributeFactory.GetAttribute(at); if (customAttribute != null) { // Apply the attribute for the control customAttribute.Apply(attributeValue, control); } } } }
实现 IAttribute
接口的两个类是 PermissionAttribute
类和 TextStyleAttribute
类。 PermissionAttribute
类用于对包含 permission
HTML 属性的 Web 控件应用声明性安全。 换句话说,如果 TextBox
控件在其 HTML 中定义了 permission 属性,那么 TextBox
将对定义的角色列表启用;否则,该控件将被禁用。
<asp:textbox id="txtData" runat="server" permission="Administrators">INFO</asp:textbox>
如果 HttpContext.User
不属于 Administrator 角色,则 TextBox
的外观如下:
TextStyleAttribute
类用于为 TextBox
Web 控件应用自定义的外观和感觉。 对于本文,我实现了一种电话样式,该样式借助 JavaScript 在您键入时将文本格式化为电话号码。 要启用此自定义样式,您需要将 textstyle
自定义 HTML 属性应用于您的文本框。
<asp:textbox id="txtPhone" runat="server" textstyle="phone" />
当您在 TextBox
中输入数字时,此 TextBox
将自动在区号、前缀和后缀之间添加“-”。
TextStyleAttribute
类与 PermissionAttribute
类的实现方式略有不同,它使用自定义属性的值来在自定义 HTML 属性中进一步定义自定义操作。 这允许您为 TextBox
实现不同的样式。 例如,您可以定义一个日期 textstyle
,它会自动将输入的数字格式化为简单的日期(mm/dd/yyyy)。 TextStyleAttribute
类实现如下:
/// <summary> /// Summary description for TextStyleAttribute. /// /// Contains the custom implementation for processing the style type /// for a System.Web.UI.WebControls.TextBox. /// </summary> public class TextStyleAttribute : IAttribute { #region IAttribute Members /// <summary> /// Applies the specified style to the web control. /// </summary> /// <param name="attributeValue">The style used for the rendered control</param> /// <param name="wc">The current control</param> public void Apply(string attributeValue, WebControl wc) { // Perform only if the control is a text box if (wc is TextBox) { // Get the style to apply for the text box TextStyle mode = (TextStyle)Enum.Parse(typeof(TextStyle), attributeValue, true); // Apply the specific style switch(mode) { case TextStyle.Phone: PhoneStyle(wc as TextBox); break; // Add more styles here. } } } #endregion /// <summary> /// Applies the 'Phone' style to the text box (ddd-ddd-dddd) /// </summary> /// <param name="text">Current TextBox control</param> private void PhoneStyle(TextBox text) { // Add custom javascript text.Attributes.Add("onKeyUp", "javascript:AutoPhone(this)"); // Set the max size for a phone number text.MaxLength = 12; } }
有关所使用的类的更多信息,请参阅随附的源代码。
结论
所呈现的两个属性实现旨在展示扩展 ASP.NET 附带的当前控件有多么容易,并为您创建自己的自定义 HTML 属性提供一个良好的开端。 如果您当前拥有自定义 ASP.NET 框架,添加此类功能将使您的框架更具可定制性。
请随时在下方留下任何评论。