自定义复制控件 - 复制任何 ASP.NET 控件
一个自定义控件,用于定位任何 ASP.NET 控件并渲染它
引言
在本文中,我尝试开发一个示例自定义控件,它模拟了复制 ASP.NET 控件并在页面其他位置显示的功能。CopyControl
可以定位任何控件,例如按钮、面板或网格,并在其自身的位置再次显示它。
在进入代码之前,我想简要介绍一下是什么让我想到这个控件的。在我的当前项目中,我为我的 Crystal Reports 创建了一个自定义工具栏,并将它放置在许多页面的每个报告的顶部。不幸的是,我没有把它作为一个 Usercontrol
。像往常一样,我的客户提出了一项变更请求,要求将控件放置在报告的顶部和底部。
由于工具栏具有许多功能,例如导出、打印,重新编写代码将非常耗时。我不想在这个时候引入 UserControl
。所以我想到了一种方法,即创建工具栏的深拷贝,并将副本放置在底部。我花了一些小时,最终意识到创建 ASP.NET 控件的深拷贝并不容易:),其中一个原因是它们不能被序列化。这让我从不同的角度思考 - 为什么不将控件在两个地方渲染呢?就这样,诞生了 CopyControl
。
CopyControl
通过在渲染时渲染目标控件来完成此操作。
让我们看一些代码。
代码片段
CopyControl
可以复制任何目标 ASP.NET 控件。我们需要在控件中添加一个属性来设置目标控件 ID
[Description("Set the Target ControlId to be copied"),
Category("Behavior")]
public String TargetControlID
{
get
{
if (ViewState["TargetControlId"] != null)
return ViewState["TargetControlId"].ToString();
return String.Empty;
}
set
{
ViewState["TargetControlId"] = value;
}
}
我们在 ViewState
中维护 TargetControlID
。
然后在 CopyControl
的 Render
方法中,我们从页面获取目标控件,并在其上调用 RenderControl()
。我们有一个 private
属性和方法来支持它。让我们看看它们
private Control TargetControl
{
get
{
return FindControlHelper(TargetControlID);
}
}
private Control FindControlHelper(String controlId)
{
Control targetControl = Page.Controls.OfType<HtmlForm>().
FirstOrDefault().FindControl(TargetControlID) as Control;
return targetControl;
}
protected override void Render(HtmlTextWriter writer)
{
if (TargetControl != null)
{
TargetControl.RenderControl(writer);
}
}
FindControlHelper()
从页面获取要复制的目标控件并返回它。最后,我们重写自定义控件的 Render()
,在目标控件上调用 RenderControl()
。
我将 CopyControl
创建为一个单独的程序集。它可以像下面这样轻松地在任何页面中引用
<%@ Register Assembly="CopyControl" Namespace="CopyControl" TagPrefix="C" %>
假设我们有一个包含许多子控件的面板
<asp:Panel ID="controlPanel" runat="server">
<table>
<tr>
<td>
<asp:Button ID="newButton" Text="New" runat="server"
onmouseout="HighLight(this);"
onmouseover="HighLight(this);" CssClass="button"
OnClick="newButton_Click" />
</td>
<td>
<asp:Button ID="deleteButton" Text="Delete"
runat="server" onmouseout="HighLight(this);"
onmouseover="HighLight(this);" CssClass="button" />
</td>
<td>
<asp:Button ID="refershButton" Text="Refresh" runat="server"
onmouseout="HighLight(this);"
onmouseover="HighLight(this);" CssClass="button" />
</td>
<td>
<Pager:AlphapheticalFilterControl ID="alphapheticalFilterControl"
runat="server" DisplayCharactersLength="15"
SelectedCssClass="selected" ButtonCssClass="button"
ArrowKeyCssClass="button" />
</td>
</tr>
</table>
</asp:Panel>
您希望此面板出现在两个位置,例如网格的顶部和底部。然后,只需将一个 CopyControl
放到网格的底部,并将它的 TargetControlID
设置为面板的 ID。
<C:CopyControlExtender TargetControlID="controlPanel" runat="server" />
就是这样。
关注点
通过在页面上放置多个 CopyControl
,我们可以使控件在页面的两个或多个位置出现,执行所有相同的功能。
历史
- 2010 年 3 月 11 日:初始发布