Click here to Skip to main content
15,881,709 members
Articles / Web Development / ASP.NET

A Custom Copy Control - Copies Any ASP.NET Control

Rate me:
Please Sign up or sign in to vote.
3.75/5 (3 votes)
11 Mar 2010CPOL2 min read 29K   356   4   1
A custom control that targets any ASP.NET control and renders it

Introduction

In this article, I have tried developing a sample custom control that simulates the functionality of copying an ASP.NET control and making it appear in another place of the page. The CopyControl can target any control say a button, panel or grid and make it appears once again in its place.

Before going into the code, I like to give a brief history about what made me think of this control. In my current project, I created a custom toolbar for my Crystal reports and placed it at the top of every report in many pages. Unfortunately, I haven't put it as a Usercontrol. As usual, a change request came from my good client asking to put the control both at the top and bottom of the reports.

Because the toolbar has many functionalities like exporting, printing it will be really a time consuming task to write the code again also. I don't want to bring the UserControl at this point. So I thought of something like creating a deep copy of the toolbar and placing the copy at the bottom. I spent some hours and finally understood that creating a deep copy of ASP.NET controls is not easy:), one of the reasons is that they are not serializable. That made me think in a different angle - why don't we render the control at two places? And.. that's the CopyControl.

The CopyControl does the trick by rendering the target control on its Rendering time.

Let's look at some code.

Bits of Code

The CopyControl can copy any target ASP.NET control. We need a property in the control for setting the target control id:

C#
[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;
    }
}

We are maintaining the TargetControlID in the ViewState.

Then in the Render method of our CopyControl, we are getting the Target Control from the page and calling the RenderControl() on it. We have a private property and method for supporting it. Let's see them:

C#
private Control TargetControl
{
    get
    {
        return FindControlHelper(TargetControlID);
    }
} 
C#
private Control FindControlHelper(String controlId)
{
    Control targetControl = Page.Controls.OfType<HtmlForm>().
	FirstOrDefault().FindControl(TargetControlID) as Control;
    return targetControl;
} 
C#
protected override void Render(HtmlTextWriter writer)
{
    if (TargetControl != null)
    {
        TargetControl.RenderControl(writer);
    }
}

The FindControlHelper() gets our target control that has to be copied from the Page and returns it. Finally, we are overriding the Render() of the custom control calling the RenderControl() on the target control.

I have created the CopyControl as a separate assembly. That can be easily referenced in any page like below:

ASP.NET
<%@ Register Assembly="CopyControl" Namespace="CopyControl" TagPrefix="C" %> 

Let's say we have a panel having many child controls:

ASP.NET
<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>  

You want this panel to appear in two places, say at the top and bottom of a grid. Then just drop a CopyControl at the bottom of the grid setting its TargetControlID to the panel's id.

ASP.NET
<C:CopyControlExtender TargetControlID="controlPanel" runat="server" />

That's all.

Points of Interest

By dropping more than one CopyControl on the page, we can make a control appear in two or more places on a page doing all the same functionalities.

History

  • 11th March, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Trigent Software Private Limited
India India
I'm a software developer from south tip of India. I spent most of the time in learning new technologies. I've a keen interest in client-side technologies especially JavaScript and admire it is the most beautiful language ever seen.

I like sharing my knowledge and written some non-popular articles. I believe in quality and standards but blames myself for lagging them.

I believe in small things and they makes me happy!

Comments and Discussions

 
QuestionHow about Dave Reed's version? Pin
Richard Deeming16-Mar-10 3:03
mveRichard Deeming16-Mar-10 3:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.