Recommended way to add child controls in CreateChildControls

P

paul.hester

Hi all,

What is the recommended way to add child controls *around* existing
child controls in the CreateChildControls method (e.g. table, row and
cell controls for layout purposes)?

Is the best way to keep a reference to the existing child controls,
clear the Controls collection and then re-add everything along with the
layout controls, or insert the layout controls around the existing
controls in the existing Controls collection?

Thanks,

Paul
 
P

paul.hester

If I try to modify the Controls collection, I get a "The Controls
collection cannot be modified because the control contains code blocks"
error because my controls contain literal content (i.e. <%=
SomeValue%>). If I change the literal content to a <%# %> tag it
doesn't get picked up and is rendered empty.

Is there any way to insert layout controls around the existing controls
and preserve the literal content?

Any help would be appreciated. I'm stuck on this one.

Thanks,

Paul
 
A

Alessandro Zifiglio

Paul, in resposne to your previous post, i have already explained to you why
that is happening and how to do it properly if you want to use inline code
block expression syntax nested within your custom control.
Let me know what about it did not convince you. Also you keep posting in two
different groups simultaneously, and it will only become hard for you to
keep track.

http://groups.google.com/group/micr...fd3d0/9526ae015a40888f?lnk=st&q=&rnum=1&hl=en

Regards,
Alessandro Zifiglio
http://www.AsyncUI.net
 
P

paul.hester

Hi Alessandro,

Thanks for your reply, and sorry about the multiple posts - I've been
getting different responses in different groups.

I haven't tried your example yet because I couldn't see how to add the
layout elements between the child controls. I need to have table, tr
and td elements around the controls and have certain controls grouped
together in a td (e.g. all validator objects in the same td). Also,
certain custom attributes will determine the layout too. I could just
have these elements in the aspx markup file, but I'm going to be using
this control all over my site and want to avoid the code repetition.

I hope I've made this clear. Any help would be appreciated.

Thanks,

Paul
 
A

Alessandro Zifiglio

Paul, you may try exposing a couple of templates. That is the alternative
route and you will get more flexibility in what you can do. Grouping your
controls within templates is much better. Just make sure that the validator
controls are grouped together with the fields they validate, either within
the same template or in different templates but within the same
NamingContainer.

You will also need to expose an itemcreated event with an argument that
gives you a handle on the template that contains the control or something
like that which you can use to retrieve the controls contained within your
templates. You wont be able to access them directly.

Another thing to be aware of is controls nested within your templates that
fire events, for these also you might want to override OnBubbleEvent in the
template and expose another generic method that fires for all click events
etc. You might have noticed this when using datacontrols like datalist,
repeater or datagrid controls, who expose ItemCreated and ItemCommand(for
events).

I wanted to include complete working code but it gets too involved and i'm
not sure this is the route you want to take anyway, but its a very common
topic and there are many examples by many bloggers or msdn itself.
Here is a simplistic example on msdn :
http://msdn2.microsoft.com/en-us/library/system.web.ui.itemplate.aspx

you should be able to take it from there, if that is what you want to do.
Following also is a simple example i wrote based on what you said here, i
hope it helps you.

Regards,
Alessandro Zifiglio
http://www.AsyncUI.net

<%@ Page Language="C#" %>

<%@ Register Assembly="AsyncUI" Namespace="AsyncUI.TestProjects"
TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
string blah = "paul";
protected void Page_Load(object sender, EventArgs e)
{
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<cc1:MyWebCustomControl ID="MyWebCustomControl1" runat="server">

<LabelsTemplate>
<asp:Label ID="Label1" runat="server"
Text="Label1"></asp:Label>
<br />
<asp:Label ID="Label2" runat="server"
Text="Label2"></asp:Label>
</LabelsTemplate>

<FormFieldTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</FormFieldTemplate>

<ValidatorTemplate>
<span style="color:Green;font-weight:bold"><%= blah
%></span>
<asp:RequiredFieldValidator Display="Dynamic"
ID="RequiredFieldValidator1" ControlToValidate="TextBox1" runat="server"
ErrorMessage="RequiredFieldValidator"></asp:RequiredFieldValidator>
<asp:RequiredFieldValidator Display="Dynamic"
ControlToValidate="TextBox2" ID="RequiredFieldValidator2" runat="server"
ErrorMessage="RequiredFieldValidator"></asp:RequiredFieldValidator>
</ValidatorTemplate>

</cc1:MyWebCustomControl>

<asp:Button ID="Button1" runat="server" Text="Submit" />
</div>
</form>
</body>
</html>

//////////////////////////////////////////////
////// Custom control
//////////////////////////////////////////////////
using System;
using System.Text;
using System.Web.UI.WebControls;
using System.Drawing;
using System.ComponentModel;
using System.Web.UI;
namespace ControlTestCenter
{

public class MyWebCustomControl : WebControl
{
private ITemplate[] templates;
public MyWebCustomControl()
: base("table")
{
//Initialization code here.
// we want to expose 3 template
templates = new ITemplate[3];
}

protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%");
writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign,
"top");
}

[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(TemplateItem))]
public ITemplate FormFieldTemplate
{
get
{
return templates[0];
}
set
{
templates[0] = value;
}
}

[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(TemplateItem))]
public ITemplate LabelsTemplate
{
get
{
return templates[1];
}
set
{
templates[1] = value;
}
}

[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(TemplateItem))]
public ITemplate ValidatorTemplate
{
get
{
return templates[2];
}
set
{
templates[2] = value;
}
}

protected override void CreateChildControls()
{
base.CreateChildControls();
// use it to get to the naming Container
TemplateItem ti = new TemplateItem();
if (LabelsTemplate != null)
{
LabelsTemplate.InstantiateIn(ti.Cells[0]);
}
if (FormFieldTemplate != null)
{
FormFieldTemplate.InstantiateIn(ti.Cells[1]);
}
if (ValidatorTemplate != null)
{
ValidatorTemplate.InstantiateIn(ti.Cells[2]);
}
Controls.Add(ti);
}
}
public enum TemplateType
{
FormFields,
Labels,
Validator
}
[ToolboxItem(false)]
public class TemplateItem : TableRow, INamingContainer
{
private TemplateType itemTypeValue;

public TemplateItem()
{
Cells.Add(new TableCell());// labels
Cells.Add(new TableCell()); // formFields
Cells.Add(new TableCell()); // validators
}

public TemplateItem(TemplateType itemType)
{
this.itemTypeValue = itemType;
Cells.Add(new TableCell());
}


public virtual TemplateType ItemType
{
get
{
return itemTypeValue;
}
}

}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top