S
Stephen Miller
Gurus,
I have a custom web control that in turn has nested child controls. I
want to be able to encapsulated and render any literal HTML and or
server controls placed between the child control's tags. This works
fine, unless I add a RequiredFieldValidator control at which point my
aspx page fails at 'WebControls.BaseValidator.CheckControlValidationProperty'
with the error message 'Unable to find control id 'TextBox1'
referenced by the 'ControlToValidate' property of
'RequiredFieldValidator1'.
My control 'Nested' contains a collection of 'NestedChild' controls
with a simple 'Caption' property. I override the 'Render' method on
the 'Nested' control and iterate though each NestedChild' in the
collection, outputting the child's literal content to a formatted
table.
The full code for my control is (please cut-n-paste to replicate my
problem):
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Collections;
using System.Collections.Specialized;
using System.Web.UI.HtmlControls;
namespace Custom.Web.UI {
[ToolboxData("<{0}:Nested runat=server></{0}:Nested2>")]
[ParseChildren(true, "NestedChild"), PersistChildren(false)]
public class Nested : WebControl, INamingContainer,
IPostBackDataHandler {
private NestedChildCollection _NestedChildren = new
NestedChildCollection();
#region Properties
[
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerDefaultProperty),
Description("A collection of nested children"),
]
public NestedChildCollection NestedChild {
get{ return _NestedChildren; }
}
#endregion
#region Overrides
protected override void CreateChildControls() {
this.Controls.Clear();
foreach (NestedChild child in _NestedChildren) {
this.Controls.Add(child);
}
}
protected override void Render(HtmlTextWriter output) {
output.Write("<b>before</b><br /><hr><br />");
//base.Render(output);
foreach(NestedChild child in _NestedChildren) {
output.Write("* " + child.Caption + "<BR>");
// Display the literal contents of NestedChild
// in a single table cell
HtmlTableCell td = new HtmlTableCell();
td.Controls.Add(child);
// Add the table cell to a new table row
HtmlTableRow tr = new HtmlTableRow();
tr.Controls.Add(td);
// Add the table row to a new table
HtmlTable table = new HtmlTable();
table.ID = this.UniqueID;
table.CellSpacing = 2;
table.CellPadding = 2;
table.Border = 1;
table.Style.Add("background-color", "#C0C0C0");
table.Controls.Add(tr);
/* FAILS NEXT LINE
Error: "Unable to find control id 'txtTest1' referenced
by the 'ControlToValidate' property of 'valTest1'"
/*
table.RenderControl(output);
}
output.Write("<br /><hr><br /><b>after</b>");
}
#endregion
#region Implements IPostBackDataHandler (postback only)
bool IPostBackDataHandler.LoadPostData(string strPostDataKey,
NameValueCollection postDataCollection) {
return true;
}
void IPostBackDataHandler.RaisePostDataChangedEvent() {}
#endregion
}
[ToolboxItem(false), DefaultProperty("Caption")]
public class NestedChild : Control{
private String m_strCaption;
public String Caption {
get { return m_strCaption; }
set { m_strCaption = value; }
}
}
public class NestedChildCollection : CollectionBase {
public NestedChild this[int nIndex]{
get { return (NestedChild) base.List[nIndex]; }
}
public void Add(NestedChild child){
base.List.Add(child);
}
public int IndexOf(NestedChild child){
return base.List.IndexOf(child);
}
}
}
When deployed the aspx page looks like:
<form id="Form1" method="post" runat="server">
<P>Nested Control</P>
<P>
<cc1:Nested id="Nested1" runat="server">
<cc1:NestedChild Caption="NestedChild">
<asp:Button id="cmdTest" runat="server" Text="Generate
Event"></asp:Button>
<asp:TextBox id="txtTest" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator id="valTest" runat="server"
ControlToValidate="txtTest"
ErrorMessage="This field is
Required.">*</asp:RequiredFieldValidator>
</cc1:NestedChild>
</cc1:Nested2></P>
<P> </P>
<P>
<asp:label id="lblResult" runat="server">lblResult</asp:label></P>
</form>
If I remove 'RequiredFieldValidator' my control render as expected.
I have noticed, that If I replace the entire formatting logic in the
'Render' method with a call to 'base.Render(output);', the
RequiredFieldValidator works as expected.
I think this is quite a technical problem and I assume that
'table.RenderControl(output)' is not preforming the necessary
server-side pre-validation to pass a 'RequiredFieldValidator'. How can
I do this?
Regards,
Stephen
I have a custom web control that in turn has nested child controls. I
want to be able to encapsulated and render any literal HTML and or
server controls placed between the child control's tags. This works
fine, unless I add a RequiredFieldValidator control at which point my
aspx page fails at 'WebControls.BaseValidator.CheckControlValidationProperty'
with the error message 'Unable to find control id 'TextBox1'
referenced by the 'ControlToValidate' property of
'RequiredFieldValidator1'.
My control 'Nested' contains a collection of 'NestedChild' controls
with a simple 'Caption' property. I override the 'Render' method on
the 'Nested' control and iterate though each NestedChild' in the
collection, outputting the child's literal content to a formatted
table.
The full code for my control is (please cut-n-paste to replicate my
problem):
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Collections;
using System.Collections.Specialized;
using System.Web.UI.HtmlControls;
namespace Custom.Web.UI {
[ToolboxData("<{0}:Nested runat=server></{0}:Nested2>")]
[ParseChildren(true, "NestedChild"), PersistChildren(false)]
public class Nested : WebControl, INamingContainer,
IPostBackDataHandler {
private NestedChildCollection _NestedChildren = new
NestedChildCollection();
#region Properties
[
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerDefaultProperty),
Description("A collection of nested children"),
]
public NestedChildCollection NestedChild {
get{ return _NestedChildren; }
}
#endregion
#region Overrides
protected override void CreateChildControls() {
this.Controls.Clear();
foreach (NestedChild child in _NestedChildren) {
this.Controls.Add(child);
}
}
protected override void Render(HtmlTextWriter output) {
output.Write("<b>before</b><br /><hr><br />");
//base.Render(output);
foreach(NestedChild child in _NestedChildren) {
output.Write("* " + child.Caption + "<BR>");
// Display the literal contents of NestedChild
// in a single table cell
HtmlTableCell td = new HtmlTableCell();
td.Controls.Add(child);
// Add the table cell to a new table row
HtmlTableRow tr = new HtmlTableRow();
tr.Controls.Add(td);
// Add the table row to a new table
HtmlTable table = new HtmlTable();
table.ID = this.UniqueID;
table.CellSpacing = 2;
table.CellPadding = 2;
table.Border = 1;
table.Style.Add("background-color", "#C0C0C0");
table.Controls.Add(tr);
/* FAILS NEXT LINE
Error: "Unable to find control id 'txtTest1' referenced
by the 'ControlToValidate' property of 'valTest1'"
/*
table.RenderControl(output);
}
output.Write("<br /><hr><br /><b>after</b>");
}
#endregion
#region Implements IPostBackDataHandler (postback only)
bool IPostBackDataHandler.LoadPostData(string strPostDataKey,
NameValueCollection postDataCollection) {
return true;
}
void IPostBackDataHandler.RaisePostDataChangedEvent() {}
#endregion
}
[ToolboxItem(false), DefaultProperty("Caption")]
public class NestedChild : Control{
private String m_strCaption;
public String Caption {
get { return m_strCaption; }
set { m_strCaption = value; }
}
}
public class NestedChildCollection : CollectionBase {
public NestedChild this[int nIndex]{
get { return (NestedChild) base.List[nIndex]; }
}
public void Add(NestedChild child){
base.List.Add(child);
}
public int IndexOf(NestedChild child){
return base.List.IndexOf(child);
}
}
}
When deployed the aspx page looks like:
<form id="Form1" method="post" runat="server">
<P>Nested Control</P>
<P>
<cc1:Nested id="Nested1" runat="server">
<cc1:NestedChild Caption="NestedChild">
<asp:Button id="cmdTest" runat="server" Text="Generate
Event"></asp:Button>
<asp:TextBox id="txtTest" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator id="valTest" runat="server"
ControlToValidate="txtTest"
ErrorMessage="This field is
Required.">*</asp:RequiredFieldValidator>
</cc1:NestedChild>
</cc1:Nested2></P>
<P> </P>
<P>
<asp:label id="lblResult" runat="server">lblResult</asp:label></P>
</form>
If I remove 'RequiredFieldValidator' my control render as expected.
I have noticed, that If I replace the entire formatting logic in the
'Render' method with a call to 'base.Render(output);', the
RequiredFieldValidator works as expected.
I think this is quite a technical problem and I assume that
'table.RenderControl(output)' is not preforming the necessary
server-side pre-validation to pass a 'RequiredFieldValidator'. How can
I do this?
Regards,
Stephen