views:

4150

answers:

9

I have a user control which is loaded in the page dynamically using the following code in Init of the Page.

Dim oCtl As Object
oCtl = LoadControl("~/Controls/UserControl1.ascx")

oCtl.Id = "UserControl11"
PlaceHolder1.Controls.Clear()
PlaceHolder1.Controls.Add(oCtl)

The user control also contains a button and I am unable to capture the button click within the user control.

+1  A: 

A few questions:

  1. At what point in the page lifecycle do you load the control?
  2. Where is the event handler code? In the control itself or do you try to hook it up to the page?
  3. What have you done so far to wire up the event?

Finally, the style guidelines for .Net specifically recommend against using any hugarian prefix warts like the o in oCtl, and you should type it as a Control rather than an object.

Joel Coehoorn
Point accepted for the hungarian prefix, shall keep that in mind for future. I am going to paste the complete code in a comment below. would appreciate your feedback
A: 

You want to only load the control when not isPostBack

lordscarlet
+1  A: 

Make sure you load the control on every postback - if the control isn't in the tree of controls when the page posts back, ASP.NET will not raise the button click event.

OdeToCode
+1  A: 

You have to ensure that the control exists on the page prior to .NET entering the "Postback event handling" step of the page lifecycle. Since the control is added dynamically you have to ensure that on every post back you recreate that control so that it can find the control to fire the event.

Dave Gray
A: 

Here is the complete code for the Page

Partial Class DynamicLoad
    Inherits System.Web.UI.Page

    Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
        If IsPostBack Then
            If Not (Session("ctl") Is Nothing) Then
                Dim oCtl As Object
                oCtl = Session("ctl")
                PlaceHolder1.Controls.Add(oCtl)
            End If
        End If
    End Sub


    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not IsPostBack Then
            Dim oCtl As Object
            oCtl = LoadControl("~/Controls/UserControl1.ascx")

            oCtl.Id = "UserControl11"
            PlaceHolder1.Controls.Clear()
            PlaceHolder1.Controls.Add(oCtl)

            Session("ctl") = oCtl
        End If
    End Sub
End Class

Here is the complete code for the user Control

Partial Class UserControl1
    Inherits System.Web.UI.UserControl
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Label1.Text = "This is Text AFTER Post Back in User Control 1"
    End Sub
End Class
A: 

Since you asked, I'd write your init event like this. I'll leave the Load event as an exercise:

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
    If IsPostBack AndAlso Session("ctl") IsNot Nothing Then
        Dim MyControl As Control = Session("ctl")
        PlaceHolder1.Controls.Add(MyControl)
    End If
End Sub

I'd also come up with a better name than 'mycontrol', but since I don't know what the control does this will have to do.

Joel Coehoorn
But this does not actually solves my postback problem from within the control
A: 

I don't know without trying it, but what if you programatically wire up the button's event handler? For instance, in the code-behind for the User Control itself, in Init or Load (not sure):

AddHandler Button1.Click, AddressOf Button1_Click

If that doesn't do anything, I know it's less efficient, but what if you don't store the User Control instance in Session and always recreate it in Page_Init every time?

Matt Blaine
+6  A: 

There are a couple of things which you are doing that are both not needed and probably causing your problems.

These are:

  1. There is no need to store the control object in the session. The Control itself should use ViewState and Session State to store information as required, not the whole instance.
  2. You shouldn't be checking for PostBack when creating the control. It must be created each time to allow both ViewState to work and the event to be wired.
  3. Controls loaded after the ViewState is loaded often have trouble operating correctly so avoid loading during the Page Load event wherever possible.

This code works for me:


Default.aspx

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="Test_User_Control._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server"><title></title></head>
<body>
    <form id="form1" runat="server">
        <asp:PlaceHolder ID="PlaceHolder1" runat="server" />
    </form>
</body>
</html>


Default.aspx.vb

Partial Public Class _Default
    Inherits System.Web.UI.Page

    Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init

        Dim control As Control = LoadControl("~/UserControl1.ascx")
        PlaceHolder1.Controls.Add(control)

    End Sub
End Class


UserControl1.ascx

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="UserControl1.ascx.vb" Inherits="Test_User_Control.UserControl1" %>
<asp:Label ID="Label1" Text="Before Button Press" runat="server" />
<asp:Button ID="Button1" Text="Push me" runat="server" />


UserControl1.ascx.vb

Public Partial Class UserControl1
    Inherits System.Web.UI.UserControl

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Label1.Text = "The button has been pressed!"
    End Sub

End Class


Aydsman
+1  A: 

I just experienced similar problem as you did, except that in my case i didn't used a session to store the control.

In my case, i located the problem in this line:

PlaceHolder1.Controls.Clear()

What i did is created a child controls and added them to the parent container on Page_Init, then processed some event handlers and after that on Page_PreRender i recreated the whole list again with the updated data.

The solution i used in this case was to create the control collection once - in the early phase of the page cycle.

ljubomir
yes, that was a my problem, too :) thanx
Marko