asp.net - route - select asp-for asp-items
Control de usuario creado dinĂ¡micamente que no puede manejar eventos en PostBack (9)
Tengo un control de usuario que se carga dinámicamente en la página utilizando el siguiente código en Init de la página.
Dim oCtl As Object
oCtl = LoadControl("~/Controls/UserControl1.ascx")
oCtl.Id = "UserControl11"
PlaceHolder1.Controls.Clear()
PlaceHolder1.Controls.Add(oCtl)
El control del usuario también contiene un botón y no puedo capturar el clic del botón dentro del control del usuario.
Aquí está el código completo de la página
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
Aquí está el código completo para el usuario 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
Asegúrese de cargar el control en cada devolución: si el control no está en el árbol de controles cuando la página se publica, ASP.NET no generará el evento de clic de botón.
Como me lo preguntaste, escribiría tu evento init así. Dejaré el evento Load como un ejercicio:
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
También encontraría un nombre mejor que "mycontrol", pero como no sé lo que hace el control, esto tendrá que hacer.
Debe asegurarse de que el control exista en la página antes de que .NET ingrese el paso "Manejo de eventos de postback" del ciclo de vida de la página. Como el control se agrega dinámicamente, debes asegurarte de que en cada publicación posterior recreas ese control para que pueda encontrar el control para disparar el evento.
Desea cargar solo el control cuando no isPostBack
No lo sé sin intentarlo, pero ¿qué ocurre si programáticamente cableas el controlador de eventos del botón? Por ejemplo, en el código subyacente para el Control de Usuario mismo, en Init o Load (no seguro):
AddHandler Button1.Click, AddressOf Button1_Click
Si eso no hace nada, sé que es menos eficiente, pero ¿qué pasa si no almacena la instancia de Control de usuario en la sesión y siempre la recrea en Page_Init cada vez?
Unas cuantas preguntas:
- ¿En qué punto del ciclo de vida de la página cargan el control?
- ¿Dónde está el código del controlador de eventos? ¿En el control mismo o intentas conectarlo a la página?
- ¿Qué has hecho hasta ahora para conectar el evento?
Finalmente, las pautas de estilo para .Net específicamente recomiendan no usar ninguna verriga de prefijos de Hugarian como o en oCtl, y debe escribirla como control en lugar de como objeto.
Hay un par de cosas que estás haciendo que no son necesarias y probablemente causen tus problemas.
Estos son:
- No es necesario almacenar el objeto de control en la sesión. El Control mismo debería usar ViewState y Session State para almacenar información según sea necesario, no la instancia completa.
- No deberías estar revisando PostBack al crear el control. Debe crearse cada vez para permitir que ViewState funcione y que el evento esté conectado.
- Los controles cargados después de cargar ViewState a menudo tienen problemas para funcionar correctamente, así que evite cargarlos durante el evento Carga de página siempre que sea posible.
Este código funciona para mí:
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">
<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
Acabo de experimentar un problema similar al tuyo, excepto que en mi caso no usé una sesión para almacenar el control.
En mi caso, localicé el problema en esta línea:
PlaceHolder1.Controls.Clear()
Lo que hice fue crear controles secundarios y los agregué al contenedor primario en Page_Init, luego procesé algunos controladores de eventos y luego en Page_PreRender recreé toda la lista nuevamente con los datos actualizados.
La solución que utilicé en este caso fue crear la colección de control una vez: en la fase inicial del ciclo de página.