Click here to Skip to main content
12,697,178 members (25,816 online)
Click here to Skip to main content
Add your own
alternative version

Stats

54.5K views
376 downloads
34 bookmarked
Posted

Duplicate WebControls at Runtime for Better Web Usability

, 2 May 2006 CPOL
Rate this:
Please Sign up or sign in to vote.
A custom control to mirror frequently-used buttons at the top and bottom of your ASP.NET web forms.

Sample Image - mirror.jpg

Introduction

It is an unfortunate reality for web application users that web pages scroll. While this is "useful" for viewing documents, it can be annoying when you are forced to scroll down to save changes to a form. And it's really "really" annoying, when your job involves doing that maybe 1,000 times a day. Astutely, my clients have noticed this, and requested that I place the Save, Cancel, Help, etc. buttons at both the top and the bottom of every page.

Obviously, you can do this without much effort. Simply duplicate the controls at the top of the page, give them new ID's, and then reference the same event handlers that the other controls are using.

But we're programmers, right? And, genetically, we "loathe" duplicate code. Who really wants to call their controls btnSave1, and btnSave2? Totally uncool.

There must be "A Better Way".

A Better Way

What if you had a way to just duplicate a group of controls so that it appeared more than once on the same page? And to have the duplication performed completely at runtime, rather than at design time?

Enter... the Mirror control. The Mirror control is a very simple custom control, whose sole function is to re-render another control so that it appears in more than one location on the page.

It turns out that the .NET control-rendering model can be used to generate the HTML for a control more than once. Any WebControl, including custom controls, will have a RenderControl() method that the Page uses to generate the control's HTML. And you can use it too...

Using the Mirror Control

As with other WebControls, using the Mirror control is horribly complicated. It works like this;

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

  • Give your control an ID, like Mirror1. If you do not, it is not strictly necessary, Visual Studio will create one for you.
  • Specify the ID of the WebControl you are mirroring through the ControlID attribute.
  • Yes, that's it.

At the top of your page, make certain to reference your custom control assembly, something like this;

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

How It Works

Very simply, the Mirror control's Render() function;

  • locates the control you have identified in the ControlID attribute, using the Page.FindControl() method.
  • forces the identified control to render itself by calling its RenderControl() method.

The actual intelligence is just a few lines of code. This is the "entire" class definition for the Mirror control. Who said custom controls have to be complicated?

/// <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);
   }
}

Caveats and Limitations

  • The control you specify will be duplicated "precisely" as rendered elsewhere. Again, "precisely". This includes things like the ID attributes. If you have JavaScript that references those ID attributes, you will probably encounter issues.
  • Avoid mirroring data-entry controls (e.g. TextBox, ListBox, CheckBox, DropDownList, ...), as only the topmost one on the page will work properly.. During a postback, the ASP.NET postback handler will only pay attention to the first control matching the ID, and load its values from there. Thus, if you change the contents of a lower-in-the-page instance of the control, its value will be lost on postback.
  • If you use absolute positioning in your layouts, make sure that you do not use them on the mirrored controls. Otherwise both sets of controls will render in the same location, one on top of the other. [Special thanks to UnderWing for pointing this out]

Tips and Tricks

  • The Mirror control is designed to duplicate one WebControl only. If you wish to duplicate a group of controls, you can use several Mirror controls, or, if they are adjacent, simply wrap your controls in a Panel, and reference the ID of the Panel instead.
  • You can mirror the same control(s) more than once on the same page, if such a thing is useful to you.
  • Avoid mirroring data-entry controls (e.g. TextBox, ListBox, CheckBox, DropDownList, ...), as explained above.
  • Avoid absolute positioning of the mirrored controls.
  • If you need to access both instances of the control, the FindControl() function will only locate one of them. However you may be able to iterate through the Page.Controls collection and locate both.

License

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

Share

About the Author

Memetican
Web Developer Sygnal Technology
New Zealand New Zealand
Michael is a systems architect who, oddly, enjoys writing code and even managing large projects. Having spent some 25 years in various computing pursuits, Mike now programs exclusively in .NET, C#, and will never, never touch C++, VB, Java, QuickBasic, Pascal, LISP, or assembly ever again. Unless he gets bored, which seems unlikely.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
GeneralCustom control for Data Pager Pin
Benjamin Sewards8-Oct-13 10:00
memberBenjamin Sewards8-Oct-13 10:00 
GeneralNice idea and control! Pin
Sandeep Mewara27-Mar-10 6:25
memberSandeep Mewara27-Mar-10 6:25 
GeneralWow. This just...works... Pin
sbguy27-Sep-06 13:43
membersbguy27-Sep-06 13:43 
QuestionDoesn't work with JavaScript event handlers Pin
UnderWing2-May-06 10:57
memberUnderWing2-May-06 10:57 
GeneralRe: Doesn't work with JavaScript event handlers Pin
MichaelWells2-May-06 15:48
memberMichaelWells2-May-06 15:48 
GeneralRe: Doesn't work with JavaScript event handlers Pin
UnderWing3-May-06 6:36
memberUnderWing3-May-06 6:36 
GeneralDoesn't work with STYLE attribute Pin
UnderWing2-May-06 10:55
memberUnderWing2-May-06 10:55 
GeneralRe: Doesn't work with STYLE attribute Pin
MichaelWells2-May-06 11:50
memberMichaelWells2-May-06 11:50 
GeneralBrilliantly Simple!!!! Pin
nutcase10-Apr-06 23:32
membernutcase10-Apr-06 23:32 
GeneralNice :) Pin
dzCepheus3-Apr-06 11:34
memberdzCepheus3-Apr-06 11:34 
GeneralId rather use an frameset or Iframe Pin
DeKale3-Apr-06 8:02
memberDeKale3-Apr-06 8:02 
GeneralRe: Id rather use an frameset or Iframe Pin
James Curran3-Apr-06 10:18
memberJames Curran3-Apr-06 10:18 
GeneralRe: Id rather use an frameset or Iframe Pin
DeKale3-Apr-06 10:42
memberDeKale3-Apr-06 10:42 
GeneralRe: Id rather use an frameset or Iframe Pin
MichaelWells3-Apr-06 13:57
memberMichaelWells3-Apr-06 13:57 
GeneralRe: Id rather use an frameset or Iframe Pin
DeKale4-Apr-06 1:25
memberDeKale4-Apr-06 1:25 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170118.1 | Last Updated 2 May 2006
Article Copyright 2006 by Memetican
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid