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

自定义复制控件 - 复制任何 ASP.NET 控件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.75/5 (3投票s)

2010年3月11日

CPOL

2分钟阅读

viewsIcon

29792

downloadIcon

373

一个自定义控件,用于定位任何 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

然后在 CopyControlRender 方法中,我们从页面获取目标控件,并在其上调用 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 日:初始发布
© . All rights reserved.