Tuesday, January 15, 2008

C# Templated Control with Design Support

I just finished an implementation of general templated control. I'll add more explanations later.



// Set an attribute reference to the designer, and define
// the HTML markup that the toolbox will write into the source.
[Designer(typeof(TemplateGroupsSampleDesigner)),
ToolboxData("<{0}:TemplateGroupsSample runat=server></{0}:TemplateGroupsSample>")]
public class TemplatedControl : WebControl, INamingContainer
{
// Field for the templates

#region Variables
private ITemplate template;
private Panel pan;
#endregion

// Ctor

#region TemplatedControl()
public TemplatedControl()
{
}
#endregion

// For each template property, set the designer attributes
// so the property does not appear in the property grid, but
// changes to the template are persisted in the control.

#region BodyTemplate
[Browsable(false),
PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate BodyTemplate
{
get { return template; }
set { template = value; }
}
#endregion

#region CreateChildControls()
protected override void CreateChildControls()
{
// Instantiate each template inside a panel
// then add the panel to the Controls collection

pan = new Panel();
template.InstantiateIn(pan);
this.Controls.Add(pan);
}
#endregion

//#region RenderBeginTag(HtmlTextWriter writer)
///// <summary>
///// This part is rendered before the template content
///// </summary>
///// <param name="writer"></param>
//public override void RenderBeginTag(HtmlTextWriter writer)
//{
// //base.Render(writer);
// writer.AddAttribute("style", "border: solid 5px red");
// writer.RenderBeginTag("div");

//}
//#endregion

//#region RenderEndTag(HtmlTextWriter writer)
///// <summary>
///// This part is rendered after template content
///// </summary>
///// <param name="writer"></param>
//public override void RenderEndTag(HtmlTextWriter writer)
//{
// writer.RenderEndTag();
//}
//#endregion
}

#region class TemplateGroupsSampleDesigner
// Designer for the TemplateGroupsSample control
public class TemplateGroupsSampleDesigner : ControlDesigner
{
// Variables

#region Variables
TemplateGroupCollection col = null;
#endregion

// Properties

#region TemplateGroups
public override TemplateGroupCollection TemplateGroups
{
get
{

if (col == null)
{
// Get the base collection
col = base.TemplateGroups;

// Create variables
TemplateGroup tempGroup;
TemplateDefinition tempDef;
TemplatedControl ctl;

// Get reference to the component as TemplateGroupsSample
ctl = (TemplatedControl)Component;

// Create a TemplateGroup
tempGroup = new TemplateGroup("Main Template");

// Create a TemplateDefinition
tempDef = new TemplateDefinition(this, "Body Template",
ctl, "BodyTemplate", true);

// Add the TemplateDefinition to the TemplateGroup
tempGroup.AddTemplateDefinition(tempDef);


// Add the TemplateGroup to the TemplateGroupCollection
col.Add(tempGroup);
}

return col;
}
}
#endregion

#region AllowResize
// Do not allow direct resizing unless in TemplateMode
public override bool AllowResize
{
get
{
if (this.InTemplateMode)
return true;
else
return false;
}
}
#endregion

// Public methods

#region Initialize(IComponent component)
public override void Initialize(IComponent component)
{
// Initialize the base
base.Initialize(component);
// Turn on template editing
SetViewFlags(ViewFlags.TemplateEditing, true);
}
#endregion

#region GetDesignTimeHtml()
// Add instructions to the placeholder view of the control
public override string GetDesignTimeHtml()
{
return CreatePlaceHolderDesignTimeHtml("Click here and use " +
"the task menu to edit the templates.");
}
#endregion
}
#endregion