65.9K
CodeProject 正在变化。 阅读更多。
Home

运行时复制 WebControls 以提高 Web 可用性

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (19投票s)

2006年4月3日

CPOL

3分钟阅读

viewsIcon

69527

downloadIcon

471

一个自定义控件,用于在 ASP.NET Web 窗体的顶部和底部镜像常用按钮。

Sample Image - mirror.jpg

引言

Web 应用程序用户面临着一个不幸的现实:网页会滚动。虽然这对于查看文档“有用”,但当您被迫向下滚动以保存对表单的更改时,可能会很烦人。当您的工作涉及每天这样做大约 1,000 次时,真的“非常”烦人。敏锐地,我的客户注意到了这一点,并要求我将保存取消帮助等按钮放在每个页面的顶部和底部。

显然,您无需费力即可做到这一点。只需复制页面顶部的控件,为其提供新的 ID,然后引用其他控件正在使用的相同事件处理程序。

但我们是程序员,对吧?并且,从基因上讲,我们“厌恶”重复代码。谁真的想调用他们的控件 btnSave1btnSave2?完全不酷。

一定有“更好的方法”。

更好的方法

如果您有一种方法可以简单地复制一组控件,使其在同一页面上出现多次怎么办?并且在运行时完全执行复制,而不是在设计时执行?

输入... Mirror 控件。 Mirror 控件是一个非常简单的自定义控件,其唯一功能是重新呈现另一个控件,使其在页面上的多个位置出现。

事实证明,.NET 控件呈现模型可用于多次生成控件的 HTML。任何 WebControl,包括自定义控件,都将具有一个 RenderControl() 方法,Page 使用该方法来生成控件的 HTML。您也可以使用它...

使用 Mirror 控件

与其他 WebControl 一样,使用 Mirror 控件非常复杂。 它是这样工作的:

<cc1:Mirror id="Mirror1" ControlID="ButtonPanel1" runat="server" />

  • 为您的控件指定一个 ID,例如 Mirror1。 如果你不这样做,虽然不是绝对必要,但 Visual Studio 会为你创建一个。
  • 通过 ControlID 属性指定要镜像的 WebControl 的 ID
  • 是的,就是这样。

在页面的顶部,请务必引用您的自定义控件程序集,如下所示;

<%@ Register TagPrefix="cc1" Namespace="MirrorControl" 
                        Assembly="MirrorControl" %>

工作原理

非常简单,Mirror 控件的 Render() 函数;

  • 使用 Page.FindControl() 方法定位您在 ControlID 属性中标识的控件。
  • 通过调用其 RenderControl() 方法,强制标识的控件自行呈现。

实际的智能只是一些代码行。这是 Mirror 控件的“整个”类定义。 谁说自定义控件必须很复杂?

 /// <summary>
 /// Mirror control.
 /// Duplicates the rendered HTML of another control on the page.
 /// </summary>
 [ToolboxData("<{0}:Mirror runat=server></{0}:Mirror>")]
 public class Mirror : WebControl
 {
    // This will be automatically populated on each Page_Load
    // with the value of the Mirror control's ControlID attribute. 
    public string ControlID = null; 
    protected override void Render (HtmlTextWriter writer)
    {
       // Ensure that the ControlID was defined
       // otherwise abort the render
       if (ControlID == null)
        return; 
       // Locate the control identified by ControlID
       Control c = Parent.FindControl (ControlID); 
       // If the specified control was not found, abort
       if (c == null)
       return; 
       // Call the control's Render function in order to
       // generate the Mirror control's HTML.
       // This, in a nutshell is the mirroring process.
       c.RenderControl (writer);
    } 
 }

警告和限制

  • 您指定的控件将被“精确地”复制,就像在其他地方呈现一样。再次强调,“精确地”。这包括诸如 ID 属性之类的内容。 如果您有引用这些 ID 属性的 JavaScript,您可能会遇到问题。
  • 避免镜像数据输入控件(例如 TextBoxListBoxCheckBoxDropDownList 等),因为页面上只有最顶端的控件才能正常工作。在回发期间,ASP.NET 回发处理程序只会关注第一个匹配 ID 的控件,并从那里加载其值。 因此,如果您更改页面上较低位置的控件实例的内容,则其值将在回发时丢失。
  • 如果您在布局中使用绝对定位,请确保不要在镜像控件上使用它们。 否则,两组控件都将在同一位置呈现,一个位于另一个之上。[特别感谢 UnderWing 指出这一点]

提示与技巧

  • Mirror 控件旨在仅复制一个 WebControl。 如果您希望复制一组控件,您可以使用多个 Mirror 控件,或者,如果它们是相邻的,只需将您的控件包装在 Panel 中,然后引用 PanelID 即可。
  • 如果您认为有用,您可以在同一页面上多次镜像相同的控件。
  • 避免镜像数据输入控件(例如 TextBoxListBoxCheckBoxDropDownList 等),如上所述。
  • 避免镜像控件的绝对定位。
  • 如果您需要访问控件的两个实例,FindControl() 函数只会定位其中一个。 但是,您可以迭代 Page.Controls 集合并定位两个实例。
© . All rights reserved.