Thursday, April 24, 2008

Enter: the Clone control...

I haven't posted in a while, so I thought I would post a little bit of ASP.NET goodness that I whipped up too, very quickly, fill a gap.

If you have ever needed to duplicate a control on your page completely (behaviour, look & feel), but just alter the position then I think this could help. I think its wonderful in its simplicity, but then I would. I wrote it. :D

A little bit of background: I needed to have the same button at the top and the bottom of a GridView control - it made sense from a usability point of view. I wasn’t happy with creating a UserControl or to copy/paste a duplicate wired up the same way, so I whipped this baby up. This clone control has some basic design-time support. The property page of the control will display a list of controls already placed on your page, will allow you to select one of them. This will be the control that will be duplicated. Pretty basic stuff (take a look and modify the FilterControl method of the CloneControlConverter if it doesn't meet your needs).

DISCLAIMER: Consider this code as Alpha quality. I am sure there will be issues with the more complex controls (just for giggles I tried it out on a GridView and it seemed to work :P ). But it’s completely up to you to determine if its production ready. If nothing else it may help point you in the right direction. So with no further ado… drum roll please... say hello to my leeedle friend!

internal class CloneControlConverter : ControlIDConverter
{
protected override bool FilterControl(Control control)
{
return !(control is CloneControl) &&
!(control is Page) &&
!(control is DataSourceControl) &&
!(control is HierarchicalDataSourceControl) &&
!(control is Content);
}
}
[ToolboxData("<{0}:CloneControl runat=\"server\" />")]
public class CloneControl : Control
{

[DefaultValue(""), IDReferenceProperty, TypeConverter(typeof(CloneControlConverter))]
public string ControlToClone
{
get
{
string value = this.ViewState["__controlToClone"] as string;
return value ?? string.Empty;
}
set
{
if (value == null)
this.ViewState.Remove("__controlToClone");

this.ViewState["__controlToClone"] = value;
}
}

protected Control FindControlToClone(string controlId)
{
Control control = this.NamingContainer.FindControl(controlId);
if (control == null)
control = this.Page.FindControl(controlId);

return control;
}

protected override void Render(HtmlTextWriter writer)
{
Control c = this.FindControlToClone(this.ControlToClone);
if (c == null)
return;

c.RenderControl(writer);
}
}














And that’s it. Nifty eh? :)



Enjoy!

No comments: