Nesting server controls with a composite control don't generate postback events

S

Stephen Miller

Hi,

I am new to web controls so please forgive me if my terminology is not
100%!

I am attempting to develop a composite control, based heavily on the
Chapter 16 sample code in James Henry's "Developing .NET Custom
Controls and Designers using C#" (see
http://www.bluevisionsoftware.com/WebSite/BookInfo.aspx?ID=7 ).

The Control is designed to emulate a windows tab control by overriding
the Render method to sending a customized HtmlTable.

The control implements IpostBackDataHandler (with
RaisePostDataChangedEvent & LoadPostData methods),
IpostBackEventHandler (with RaisePostBackEvent method) and
InamingContainer.

This works fine, and I am very happy with the results, however when I
nest any server controls that require PostBack, the nested controls
fail to raise events.

The ASPX for the custom control takes the following form. As an
example, a standard Button control has been placed between the second
tab's <cc1:Tab></cc1:Tab> tags.

<cc1:TabControl id="myTab" runat="server">
<cc1:Tab headertext="Tab1">First tab's content goes here</cc1:Tab>
<cc1:Tab headertext="Tab2">
Second tab's content includes a nested control:
<asp:Button id="cmdTest" runat="server" Text="Click me!">
</asp:Button>
</cc1:Tab>
<cc1:Tab headertext="tab3">Third tab's content goes here</cc1:Tab>
</cc1:TabControl>

In the codebehind, a function 'cmdTest_Click' has been declared to
handle the 'cmdTest.Click' event. It is expected that clicking the
button should call this function, however this doesn't happen.
Interestingly, the page appears to make a round-trip to the server, it
just fails to call events bound to the nested control. If the button
is moved outside the custom control, it behaves as expected.

What should I do to enable nested controls to generate their own
events? If someone could post some code snippits, I would be much
obliged!

Thanks,

Stephen
 
S

Stephen Miller

John,

cmdTest.Click is declared in the codebehind as follows. I'm not sure
that it's declaration is the problem, as the Server control (and it's
click event) work fine when the Button control is moved outside my
custom control.

Placed normally on an ASPX page the button control works as expected:

<this_works_fine>
<asp:Button id="cmdTest" runat="server" Text="Generate event" />
</this_works_fine>

My problem is that when, the same control is nested as literal XML
within my custom control, the control renders but is unable to call
the cmdTest.Click event:

<this_does_not_work>
<cc1:TabControl id="tabTest" runat="server">
<cc1:Tab>
<asp:Button id="cmdTest" runat="server" Text="Generate event" />
</cc1:Tab>
</cc1:TabControl>
</this_does_not_work>

In this example, the codebehind for the Button control is:

<codebehind>

Protected WithEvents lblTest As
System.Web.UI.HtmlControls.HtmlGenericControl
Protected WithEvents cmdTest As System.Web.UI.WebControls.Button

Private Sub cmdTest_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles cmdTest.Click
lblTest.InnerHtml = "cmdTest Clicked"
End Sub

</codebehind>

Note, this problem occurs with any server control nested as literal
XML between my custom control's <cc1:Tab> & </cc1:Tab> tags.

Thanks,

Stephen
 
J

John Saunders

Stephen,

If you've supplied enough of your control for me to reproduce this, then I
missed it. Perhaps you could post a reproducer.

I'd also suggest you set a breakpoint in your Page_Load and see whether
cmdTest is ever set to anything.
 
S

Stephen Miller

S

Stephen Miller

James,

Thanks for that! The overrided CreateChildControls method is obviously
the key, and my nested button control now correctly generates events.

However, I think I have exposed a more complicated problem. If you
nest within the custom control's tab a standard TextBox control
('txtRequired'), with a linked RequiredFieldValidator control
('valRequired'), the TextBox's properties do not appear to be
available to the RequiredFieldValidator when rendering.

The error message thrown is:
"Unable to find control id 'txtRequired' referenced by the
'ControlToValidate' property of 'valRequired'."

Is there something I need to add to instatiate (if that the right
term) the nested controls?

My test page now includes:

<test.aspx.vb>
...
Protected WithEvents txtRequired As System.Web.UI.WebControls.TextBox
Protected WithEvents valRequired As
System.Web.UI.WebControls.RequiredFieldValidator
...
</test.aspx.vb>

<test.aspx>
...
<cc1:Tab headertext="tab1">
<asp:TextBox id="txtRequired" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator id="valRequired" runat="server"
ErrorMessage="This field is Required."
ControlToValidate="txtRequired">*</asp:RequiredFieldValidator>
</cc1:Tab>
...
</test.aspx>

Thanks again for your help,

Stephen
 
J

John Saunders

Both the validator control and the control being validated need to be within
the same INamingContainer. This sucks. I found this when I wanted them in
separate templates. Didn't work.
--
John Saunders
Internet Engineer
(e-mail address removed)

Stephen Miller said:
James,

Thanks for that! The overrided CreateChildControls method is obviously
the key, and my nested button control now correctly generates events.

However, I think I have exposed a more complicated problem. If you
nest within the custom control's tab a standard TextBox control
('txtRequired'), with a linked RequiredFieldValidator control
('valRequired'), the TextBox's properties do not appear to be
available to the RequiredFieldValidator when rendering.

The error message thrown is:
"Unable to find control id 'txtRequired' referenced by the
'ControlToValidate' property of 'valRequired'."

Is there something I need to add to instatiate (if that the right
term) the nested controls?

My test page now includes:

<test.aspx.vb>
...
Protected WithEvents txtRequired As System.Web.UI.WebControls.TextBox
Protected WithEvents valRequired As
System.Web.UI.WebControls.RequiredFieldValidator
...
</test.aspx.vb>

<test.aspx>
...
<cc1:Tab headertext="tab1">
<asp:TextBox id="txtRequired" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator id="valRequired" runat="server"
ErrorMessage="This field is Required."
ControlToValidate="txtRequired">*</asp:RequiredFieldValidator>
</cc1:Tab>
...
</test.aspx>

Thanks again for your help,

Stephen



"James Henry [BlueVision]" <developingdotnetcustomcontrols@bluevision>
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top