views:

304

answers:

2

I'm sure this question has been asked a million times, however I haven't been able to find an answer that solves my problem.

I am programmatically adding some custom user controls to a PlaceHolder which I have on a simple aspx page. All of the user controls Postback's work correctly except for one which has a Gridview on it.

For some reason any postback that gets fired from within this control, does not call the specified event on the first click, however all future clicks it will work fine. I have no idea why this is the case, but many solutions I have found, suggest adding an ID to the ascx User Control, however this doesn't work in my case.

I've taken a look at the source file for the page that gets generated before and after the first click, javascript used for calling the postback changes, i.e

Before first click: onclick="javascript:__doPostBack('tmpControlID$sgvPrimaryEmploymentHistory','Select$0')"

After first click: onclick="javascript:__doPostBack('OFFHome1$tmpControlID$sgvPrimaryEmploymentHistory','Select$0')"

OFFHome1 is the parent user control which exists on the aspx page. All other controls are added to a placeholder in this control, i.e.

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="OFFHome.ascx.vb" Inherits="UmbracoUserControls.OFFHome" %>
<asp:PlaceHolder ID="phOFFSection" runat="server"></asp:PlaceHolder>

Nothing to complicated. Then in the code behind the controls are loaded into the placeholder using the following:

Private Sub LoadNextOFFStep()
    Dim ControlName As String = "TestControl.ascx"
    phOFFSection.Controls.Clear()
    If ControlName IsNot Nothing AndAlso ControlName <> String.Empty Then
        Dim NewControl As Object = LoadControl(ControlName)

        With NewControl
            .ID = USERCONTROLNAME
            Dim StepCompleted As Boolean = .FillControl()
            If StepCompleted Then
                Exit Sub
            End If
            Dim AllowSkip As Boolean = .AllowSkip()
            btnSkip.Visible = AllowSkip
        End With
        phOFFSection.Controls.Add(NewControl)
    End If
End Sub

Again, nothing overly complicated. The USERCONTROLNAME is just a const with the value "tmpControlID" in it.

The control that is giving me trouble is a little complicated, I was originally using a custom GridView control that we have created, but have removed it and replaced it with the standard asp one to see if the problem still occurs, and it does.

Any button, on control which fires off a postback will fail the first time, and all future click will work correctly. On the first click the Page_Load event will get called, but that is it.

What am I doing wrong??

A: 

Well... the answer to the first question is simple: It fails the first time because the ID of the control (or rather, in the postback script) is different on subsequent page loads. It works on subsequent clicks because the control ID stays the same.

Now as to WHY that is... much tougher! But probably something to do with the order of operations here.

Try explicitly setting the NamingContainer value for NewControl:

    With NewControl
        .NamingContainer = OffHomeOne; // whatever
        .ID = USERCONTROLNAME
Bryan
Turns out I can't explicitly set the NamingContainer as it is a readonly property.
D'oh. You're right. Well... this is definitely related to your problem. Out of curiosity, can you call this method in Init instead of Page_Load? Any functional difference?
Bryan
Doesn't seem to make any difference. I've tried using a datagrid instead of gridview, and on the first click, the grid actually disappears. And on future clicks it works correctly...
A: 

After far too much time spent on this, I have finally worked it out.

It was to do with the order of events, however just not where I had thought. The FillControl function was getting called before User Control had been added to the PlaceHolder. I changed this so that it gets called after the User Control was added to the PlaceHolder and now it works first time.

Basically the code looks like this now:

Private Sub LoadNextOFFStep()
    Dim ControlName As String = "TestControl.ascx"
    phOFFSection.Controls.Clear()
    If ControlName IsNot Nothing AndAlso ControlName <> String.Empty Then
        Dim NewControl As Object = LoadControl(ControlName)

        With NewControl
            .ID = USERCONTROLNAME
            Dim AllowSkip As Boolean = .AllowSkip()
            btnSkip.Visible = AllowSkip
        End With
        phOFFSection.Controls.Add(NewControl)
        Dim StepCompleted As Boolean = CType(phOFFSection.Controls(0), Object).FillControl()
        If StepCompleted Then
            LoadNextOFFStep()
            Exit Sub
        End If
    End If
End Sub

Thanks for everyone's help.