ASP.NET 服务器控件 - Updown 控件 1






4.26/5 (12投票s)
2002年3月25日
9分钟阅读

311642

1893
关于实现 ASP.Net 自定义服务器控件的教程
正如文章标题所述,我们将尝试解释创建 Web 控件的步骤,特别是 Up-Down 控件。此控件的功能与 MFC 的 Up-Down 控件和 Windows Forms 的 System.Windows.Forms.NumericUpDown
控件相同。我们将尽力详细解释这些步骤。.NET Framework 文档中提供了大量信息。关键在于如何应用这些信息来创建一个对您日常网页操作有用的控件。
您可以通过两种方式构建服务器控件。
- 复合控件
- 自定义控件
我们不会详细介绍这两种类型的定义。有关这方面的信息,.NET Framework 文档中已经提供了很好的内容。简单来说,复合控件是利用一个或多个现有服务器控件的服务器控件,而自定义控件则非常类似于实现您的 Windows 控件,您将通过实现 OnPaint
事件来处理绘制。同样,对于自定义控件,您将在 Render
事件处理程序中提供控件自己的呈现。我们将在文章后面讨论这些细节。
我们为什么要创建自定义控件?
如果您查看 Up-Down 控件,它由一个文本框和两个用于增加或减少值的按钮组成。这意味着可以使用一个由一个 asp:TextBox
和两个 asp:ImageButton
控件组成的复合控件来实现此功能。但我们决定创建自定义控件并自己渲染 HTML
标签。
我们选择此路线有几个原因。尽管 ASP.NET 文档指出服务器控件可以生成与浏览器兼容的 HTML
标签,但根据我们的实际经验,我们发现对于 Internet Explorer 以外的浏览器,HTML 代码生成非常不一致。另一个原因是,每次单击微调控件时,控件的值都会发生变化。这意味着我们将不得不在客户端管理状态,而不是为每次单击执行回发,因为那不是一个非常有效的解决方案,它会产生大量网络流量。因此,我们将不得不发出客户端 JavaScript 来管理状态。
让我们开始吧
定义控件
每个服务器控件都继承自 Control
或 WebControl
。因此,第一步是创建一个继承自这些类之一的控件类。WebControl
本身继承自 Control
类。将控件类继承自 WebControl</u> 的优点是,除了
Control
的通用属性外,您的控件还将继承 Web 控件常用属性的实现,例如 Width
、Height
、Font
等。因此,我们决定利用它并从 WebControl
类继承我们的控件。
[ToolboxData("<{0}:UpDownControl Runat=server>/>")]
[Designer(typeof(UpDownControl))]
public class UpDownControl : WebControl, IPostBackDataHandler
您应该注意到,我们指定了该控件将提供 IPostBackDataHandler
接口的实现。这样做的原因是我们控件将保存用户通过微调器增减指定的值,并且当 Form
被回发处理时,这些值必须传达给页面。IPostBackDataHandler
接口提供了两个方法,LoadPostData
和 RaisePostDataChangedEvent
,我们的控件将实现这两个方法来处理来自包含页面的回发事件。
定义哪些属性?
现在,让我们看看除了标准的 Color
、Font
等属性外,我们还需要哪些自定义属性。由于我们的控件是 Up-Down 控件,这意味着我们需要一些图形来显示我们的向上和向下箭头。因此,我们有两个属性可用于设置/获取向上-向下箭头的 URL。
[Category("Text")]
[Description("URL for up arrow image")]
public string UpArrowImgUrl
{
get{return this.m_strUpArrowImg;}
set{this.m_strUpArrowImg = value;}
}
然后,我们需要提供一种方法来控制向上-向下箭头应显示在文本框的哪一侧。可以是左侧或右侧。因此,我们需要定义一个属性来获取/设置此值。我们决定使用 enum
类型而不是仅使用 int
类型,这样可以更具描述性地设置此值,也就是说,我们通过“Left”和“Right”值来设置,而不是将值设置为 0 或 1。
public enum ArrowsPosition
{
Left = 0,
Right = 1,
}
[Category("Appearance")]
[Description("Specify if up-down arows will be displayed on right side or not.")]
public ArrowsPosition ArrowsPositionSide
{
get{return this.m_enumArrowsPosition;}
set{this.m_enumArrowsPosition = value;}
}
接下来,我们需要指定箭头距离文本框的距离。这就像在两个 HTML 对象之间提供间距。因此,我们定义了 ArrowsSpacing
属性,我们可以对其进行设置/获取。
[Category("Appearance")]
[Description("Specify the spacing between text-box and up-down arrows.")]
public int ArrowsSpacing
{
get{return this.m_iArrowsSpacing;}
set{this.m_iArrowsSpacing = value;}
}
然后是影响保存在文本框中的值的属性。例如,与 System.Windows.Forms.NumericUpdown
一样,我们指定了控制最大最小值和增量的属性。有关更多详细信息,请参阅文章随附的源代码控件。
控件的渲染
要为自定义服务器控件渲染 HTML 标签,提供对 Render</u> 方法的实现非常重要,该方法位于您的控件 class 中。此方法使控件有机会渲染其内容或任何它想要输出到浏览器的内容。
Render
方法只有一个参数,HtmlTextWriter
,它充当将 HTML 内容写入网页的输出流。
protected override void Render(HtmlTextWriter output) { }
因此,在此方法中,我们渲染所有 HTML 标签以显示文本框和向上-向下箭头图像。我们发出 input
和 img
来渲染此用户界面,并显示正确类型的图像,我们从 UpArrowImgUrl
和 DownArrowImgUrl
属性获取值。此渲染已在控件类的两个私有方法 AddTextSpanSection
和 AddImageSection
中实现。
strRender.Append("\n<table cellspacing=\"0px\" cellpadding=\"0px\"");
strRender.Append(" height=\"");
strRender.Append(this.Height + "\">");
// Add up arrow row
strRender.Append("\n<tr>");
strRender.Append("\n<td valign=\"bottom\">");
strRender.Append("<img border=0 title=\"Increment value\" src=\"");
strRender.Append(this.m_strUpArrowImg);
strRender.Append("\"");
strRender.Append(" onclick=\"javascript:" + this.UpArrowClickFunction + "();");
strRender.Append("\">");
strRender.Append("\n</td>");
strRender.Append("\n</tr>");
处理事件
渲染只是实现服务器控件的一部分。这就像给一个人提供身体。现在这个东西也需要一个大脑,在网页控件的世界里,大脑的力量就是对发生的各种操作做出反应。我们正在实现一个向上-向下微调控件;这意味着控件必须对用户单击向上/向下箭头的操作做出反应。我们通过实现显示箭头的每个 img
标签的 onclick
事件来提供此能力。如果您查看上面的代码,我们在渲染 img
控件时调用 UpArrowClickFunction
。此私有方法返回处理向上箭头图像控件单击事件的客户端 javascript
函数的名称。使用相同的方法,我们为向下箭头图像控件的单击事件添加了客户端事件处理程序。
strRender.Append("<img border=0 title=\"Decrement value\" src=\"");
strRender.Append(this.m_strDownArrowImg);
strRender.Append("\"");
strRender.Append(" onclick=\"javascript:" + this.DownArrowClickFunction + "();");
strRender.Append("\">");
管理控件的状态
Up-down 控件没有引发回发事件的方法。这并非完全正确,但我们不希望此控件为每次单击箭头图像而执行回发。这意味着我们将不得不使用一些客户端脚本来管理状态。但首先,我们需要一些占位符来保存状态。我们使用一个旧的技巧,即在页面中使用一个隐藏的输入控件。当用户提交表单或任何其他控件触发回发事件时,此输入将用于将文本框中存储的值传达给页面。
ASP.NET 框架有助于完成此任务。Page
类有一个 RegisterHiddenField
方法,该方法会在表单上自动注册一个隐藏字段。当页面呈现时,此隐藏字段也会在页面上呈现。我们在 OnPreRender</u> 事件处理程序中调用此方法。
RegisterHiddenField
方法有两个参数,一个用于指定隐藏控件的唯一 ID,第二个参数用于存储控件的初始值。
protected override void OnPreRender(EventArgs args)
{
base.OnPreRender(args);
if (Page != null)
{
Page.RegisterHiddenField(HelperID, Text);
}
}
在控件实现中,我们提供了一个私有属性 HiddenID
,它使用控件的 ClientID
属性为隐藏变量生成唯一的 ID。
状态如何传达给页面?
好的,我们已经渲染了控件,处理了箭头上的单击事件,并管理了状态。现在剩下最后一件事,控件状态的更改将如何传达,如果控件希望在其状态更改时引发任何事件,该如何发生?以下是需要遵循的步骤来连接所有这些。
- 第一步是告诉包含页面的页面,当发生回发时,我们的控件需要被通知。在 .NET Framework 中,回调是通过事件和委托完成的。
Page
类有一个RegisterRequiresPostBack
方法,需要调用该方法并传入我们控件的引用。此方法调用将我们的控件注册到Page
以便接收事件。protected override void OnInit(EventArgs e) { base.OnInit(e); if (Page != null) { Page.RegisterRequiresPostBack(this); } }
- 将控件注册到
Page
后,现在我们需要弄清楚我们要如何处理该事件。最重要的是,这一切是如何发生的。在文章开头定义控件时,我们提到控件类将实现IPostBackDataHandler
接口。当Page
为控件引发回发事件时,它会调用控件上的LoadPostData
方法。此方法有两个参数。send 参数包含所有已回发的值的集合,因此我们可以从该集合中获取已回发的值。然后,您可以将已回发的值与当前值进行比较,以检查值是否已更改。如果值已更改,则从此方法返回true
,表示状态已更改。这将引发控件上的更改事件。bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) { string presentValue = this.Text; string postedValue = postCollection[HiddenID]; // If two values don't match, then update the value. if (!presentValue.Equals(postedValue)) { this.Text = postedValue; // Indicate the state of this control has changed. return true; } // If there was no change in the data, then indicate that there is // no change in state by returning false. return false; }
- 如果
LoadPostData
方法返回true
,Page
将调用控件上的RaisePostDataChangedEvent
,让它有机会引发自己的事件或执行任何所需的处理。
如何在页面上使用此控件?
在您希望使用此控件的页面中,第一步是在页面顶部使用 @Register
指令注册它。
<%@ Register TagPrefix="Softomatix"
Namespace="ASPNet_Controls"
Assembly="ASPNet_Controls"
%>
然后将其包含在页面中,就像其他服务器控件一样,指定您想要分配给该控件的属性值。
<form id="UpDownControlClient" method="post" runat="server">
<Softomatix:UpDownControl
Runat="server"
Height="30"
UpArrowImgUrl="images\UpArrow_10x10.gif"
DownArrowImgUrl="images\DownArrow_10x10.gif"
ArrowsPositionSide="Right"
ArrowsSpacing="2"
Text="2"
MaxValue="10"
MinValue="0"
Increment="1"
id="UpDownControl1">
</Softomatix:UpDownControl>
<asp:Button Runat="server" ID="wndSubmit" Text="Submit">
</asp:Button>
</form>
下一步?
在本文中,我们展示了控件的实现。在整个代码中,您会注意到我们在属性和类定义上都使用了属性。创建控件后,您可能希望将其包含在工具箱中,以便可以通过从工具箱拖放到页面上来使用它。在下一篇文章中,我们将扩展实现,以便将此控件包含在服务器控件工具箱中。
联系我们
如果您有任何问题或建议,可以在本文中发表评论,或直接通过 softomatix@pardesiservices.com 联系我们,或访问我们的网站 Softomatix。