2011-01-20 33 views
5

Tengo una página con un ScriptManager, una lista desplegable de HTML genérico (<select>) y un UpdatePanel. El UpdatePanel contiene un PlaceHolder (por ahora). Durante Page_Load, se agregan varios controles de usuario al PlaceHolder (en realidad, son varias instancias del mismo control de usuario). El número a agregar no se conoce hasta que la página se carga, por lo que deben cargarse dinámicamente. La lista desplegable se completa con el mismo número de elementos de menú, y también hay javascript en la página (usando jQuery) para mostrar solo uno de los controles a la vez dependiendo del estado de la lista desplegable.Agregar PostBackTriggers y AsyncPostBackTriggers a UpdatePanel para controles de nieto generados dinámicamente

Cada control de usuario tiene dos botones que deben generar una devolución de datos asincrónica, una lista desplegable que debe generar una devolución de datos asincrónica en un cambio en el valor seleccionado y un botón que debe generar una devolución de datos síncrona. Si yo no estaba generando los controles de forma dinámica, y si había un solo control, la estructura sería algo así como:

<asp:UpdatePanel ID="myUpdatePanel" runat="server" UpdateMode="Conditional" 
       ChildrenAsTriggers="false"> 
    <ContentTemplate> 
     <asp:TextBox ID="textBox1" runat="server" /> 
     <asp:TextBox ID="textBox2" runat="server" /> 
     <asp:Button ID="asyncButton1" runat="server" Text="Button1" 
        onclick="asyncButton1_Click" /> 
     <asp:DropDownList ID="asyncDropDown" ruant="server" AutoPostBack="true" 
        OnSelectedIndexChanged="asyncDropDown_SelectedIndexChanged" /> 
     <asp:Button ID="asyncButton2" runat="server" Text="Button2" 
        OnClick="asyncButton2_Click" /> 
     <asp:Button ID="syncButton" runat="server" Text="SyncButton" 
        OnClick="syncButton_Click" /> 
    </ContentTemplate> 
    <Triggers> 
     <asp:AsyncPostBackTrigger ControlID="asyncButton1" EventName="Click" /> 
     <asp:AsyncPostBackTrigger ControlID="asyncButton2" EventName="Click" /> 
     <asp:AsyncPostBackTrigger ControlID="asyncDropDown" 
      EventName="SelectedIndexChanged" /> 
     <asp:PostBackTrigger ControlID="syncButton" /> 
    </Triggers> 
</asp:UpdatePanel> 

Por supuesto, todos los controles dentro de la ContentTemplate sería en realidad parte de cada control de usuario.

Agregar los desencadenadores en el lado del servidor no parece funcionar porque ningún ControlID parece ayudar al UpdatePanel a encontrar los controles relevantes. Puedo utilizar el ID del mando o UniqueID del control, y no funciona, y me sale un error en la línea de

A control with ID 'ctl00$ContentPlaceHolder1$ctl01$asyncButton1' could not be 
found for the trigger in UpdatePanel 'myUpdatePanel'. 

tanto, me pregunto si me tengo que registrar los disparadores en el cliente en lugar de utilizar ASP.NET Ajax. Encontré this page que básicamente explica cómo. Sin embargo, no sé cómo tener en cuenta el EventName. Los ejemplos que he visto hasta ahora meramente han agregado clics de botón, pero no sé cómo manejar el evento SelectedIndexChanged de DropDownList.

¿Alguna ayuda aquí? ¿Hay ejemplos que he echado de menos? No ayuda, por supuesto, que el método en el enlace que brindé parece ser "no oficial", por lo que no veo ningún documento de MSDN sobre el tema.

Gracias!

+0

¿Está utilizando .NET Framework 4.0? Lo pregunto porque ahora tiene más control sobre Control.ClientID: http://msdn.microsoft.com/en-us/library/system.web.ui.control.clientid.aspx –

+0

@Tim No, esto tiene que ser así. NET 3.5 por ahora. – Andrew

+0

etiquetados como 3.5. Voy a verlo más de cerca más tarde. –

Respuesta

6

Mi sugerencia sería retirar todos sus controles, incluido este UpdatePanel, de este UpdatePanel en un UserControl. Defina los eventos en su usercontrol que se generan cuando se hace clic en los botones o se cambia el índice seleccionado de la lista desplegable. Maneje estos eventos en su página que contiene el marcador de posición (en un solo UpdatePanel, condicional, sin desencadenantes). Llame al método de actualización del panel de actualización principal de forma manual si agrega UserControls.

Para aclarar lo que quiero decir echar un vistazo a siguiente ejemplo:

Principal-aspx:

<asp:UpdatePanel ID="Upd1" runat="server" UpdateMode="Conditional"> 
    <ContentTemplate> 
    <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder> 
    </ContentTemplate> 
</asp:UpdatePanel> 

Codebehind:

Private Property UserControlCount() As Int32 
     Get 
      If ViewState("UserControlCount") Is Nothing Then 
       ViewState("UserControlCount") = 1 
      End If 
      Return DirectCast(ViewState("UserControlCount"), Int32) 
     End Get 
     Set(ByVal value As Int32) 
      ViewState("UserControlCount") = value 
     End Set 
    End Property 

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
     recreateUserControls() 
    End Sub 

    Private Sub recreateUserControls() 
     For i As Int32 = 1 To Me.UserControlCount 
      Dim uc As DynamicControls = DirectCast(Me.LoadControl("DynamicControls.ascx"), DynamicControls) 
      uc.ID = "DynamicControls_" & i 
      Addhandlers(uc) 
      Me.PlaceHolder1.Controls.Add(uc) 
     Next 
    End Sub 

    Private Sub Addhandlers(ByVal uc As DynamicControls) 
     AddHandler uc.asyncButton1Clicked, AddressOf ucAsyncButton1Clicked 
     AddHandler uc.asyncButton2Clicked, AddressOf ucAsyncButton2Clicked 
     AddHandler uc.syncButtonClicked, AddressOf ucSyncButtonClicked 
     AddHandler uc.asyncDropDownSelectedIndexChanged, AddressOf ucAsyncDropDownSelectedIndexChanged 
    End Sub 

    Private Sub addUserControl() 
     Me.UserControlCount += 1 

     Dim uc As DynamicControls = DirectCast(Me.LoadControl("DynamicControls.ascx"), DynamicControls) 
     uc.ID = "DynamicControls_" & Me.UserControlCount 
     Addhandlers(uc) 
     Me.PlaceHolder1.Controls.Add(uc) 

     Upd1.Update() 
    End Sub 

    Private Sub ucAsyncButton1Clicked(ByVal sender As Object, ByVal e As EventArgs) 
     'only to demonstrate how to add control dynamically and update the UpdatePanel' 
     addUserControl() 
     Me.Upd1.Update() 
    End Sub 

    Private Sub ucAsyncButton2Clicked(ByVal sender As Object, ByVal e As EventArgs) 
    End Sub 

    Private Sub ucSyncButtonClicked(ByVal sender As Object, ByVal e As EventArgs) 
    End Sub 

    Private Sub ucAsyncDropDownSelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) 
    End Sub 

ascx que sostiene su controles:

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="DynamicControls.ascx.vb" Inherits="AJAXEnabledWebApplication1.DynamicControls" %> 
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %> 

<asp:UpdatePanel ID="myUpdatePanel" runat="server" UpdateMode="Conditional" 
       ChildrenAsTriggers="false"> 
    <ContentTemplate> 
     <asp:TextBox ID="textBox1" runat="server" /> 
     <asp:TextBox ID="textBox2" runat="server" /> 
     <asp:Button ID="asyncButton1" runat="server" Text="Button1" /> 
     <asp:DropDownList ID="asyncDropDown" runat="server" AutoPostBack="true" /> 
     <asp:Button ID="asyncButton2" runat="server" Text="Button2" /> 
     <asp:Button ID="syncButton" runat="server" Text="SyncButton" /> 
    </ContentTemplate> 
    <Triggers> 
     <asp:AsyncPostBackTrigger ControlID="asyncButton1" EventName="Click" /> 
     <asp:AsyncPostBackTrigger ControlID="asyncButton2" EventName="Click" /> 
     <asp:AsyncPostBackTrigger ControlID="asyncDropDown" EventName="SelectedIndexChanged" /> 
     <asp:PostBackTrigger ControlID="syncButton" /> 
    </Triggers> 
</asp:UpdatePanel> 

Codebehind de control de usuario:

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

    Public Event asyncButton1Clicked(ByVal sender As Object, ByVal e As System.EventArgs) 
    Public Event asyncButton2Clicked(ByVal sender As Object, ByVal e As System.EventArgs) 
    Public Event syncButtonClicked(ByVal sender As Object, ByVal e As System.EventArgs) 
    Public Event asyncDropDownSelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) 

    Private Sub asyncButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles asyncButton1.Click 
     RaiseEvent asyncButton1Clicked(sender, e) 
    End Sub 

    Private Sub asyncButton2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles asyncButton2.Click 
     RaiseEvent asyncButton2Clicked(sender, e) 
    End Sub 

    Private Sub syncButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles syncButton.Click 
     RaiseEvent syncButtonClicked(sender, e) 
    End Sub 

    Private Sub asyncDropDown_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles asyncDropDown.SelectedIndexChanged 
     RaiseEvent asyncDropDownSelectedIndexChanged(sender, e) 
    End Sub 
End Class 

En esta manera usted no tendrá problemas con la ClientID.

Adición: Si necesita acceder a los controles de sus UserControls En el caso de los manipuladores, utilice uno de los siguientes dos opciones:

  1. fundido NamingContainer del remitente al tipo del control de usuario: Dim uc As DynamicControls = DirectCast(DirectCast(sender, Control).NamingContainer, DynamicControls)
  2. reemplaza todas las ocurrencias de (ByVal sender As Object, ByVal e As System.EventArgs) con (uc as DynamicControls). En esta forma se añade la referencia de su control de usuario al evento como parámetro y se puede acceder a las propiedades públicas de la misma a partir de la página, Fe:

    dim txt1 as String = uc.Text1 
    

Si ha expuesto una propiedad Texto1 en el control de usuario:

Public Property Text1() As String 
    Get 
     Return textBox1.Text 
    End Get 
    Set(ByVal value As String) 
     textBox1.Text = value 
    End Set 
End Property 

La segunda opción es la manera más limpia y legible.

actualización: De acuerdo con su comentario: usted debe colocar el UpdateProgress en el control de usuario dentro del UpdatePanel que se actualiza. Recuerde configurar el AssociatedUpdatePanelID correctamente. Por ejemplo:

<asp:UpdatePanel ID="UdpForm" runat="server" UpdateMode="conditional" ChildrenAsTriggers="false" > 
    <ContentTemplate> 
    <asp:panel ID="FormPanel" runat="server"> 
     <asp:UpdateProgress ID="UpdateProgress1" DynamicLayout="true" runat="server" AssociatedUpdatePanelID="UdpForm" DisplayAfter="0" > 
      <ProgressTemplate> 
      <div class="progress"> 
       <asp:Image ID="ImgProgress1" runat="server" ImageUrl="~/images/ajax-loader-arrows.gif" ToolTip="loading..." />&nbsp;please wait... 
      </div> 
      </ProgressTemplate> 
     </asp:UpdateProgress>  
     <asp:FormView ID="FormView1" runat="server" DefaultMode="ReadOnly" > 
      <ItemTemplate></ItemTemplate> 
      <EditItemTemplate></EditItemTemplate> 
      <InsertItemTemplate></InsertItemTemplate> 
      <EmptyDataTemplate> 
      </EmptyDataTemplate> 
      <PagerTemplate > 
      </PagerTemplate> 
     </asp:FormView> 
    </asp:panel> 
    </contenttemplate> 
</asp:UpdatePanel> 

<asp:UpdatePanel ID="UpdContent" runat="server" UpdateMode="conditional" ChildrenAsTriggers="false" > 
    <ContentTemplate> 
    <asp:Panel ID="PnlMain" runat="server"> 
     <asp:UpdateProgress ID="UpdateProgress2" DynamicLayout="true" runat="server" AssociatedUpdatePanelID="UpdContent" DisplayAfter="0" > 
      <ProgressTemplate> 
      <div class="progress"> 
       <asp:Image ID="ImgProgress1" runat="server" ImageUrl="~/images/ajax-loader-arrows.gif" ToolTip="loading..." />&nbsp;please wait... 
      </div> 
      </ProgressTemplate> 
     </asp:UpdateProgress> 

     Content 

    </asp:Panel> 
</ContentTemplate> 
    <Triggers ></Triggers> 
</asp:UpdatePanel> 
+0

Gracias. He depurado la aplicación, y creo que esto más o menos funciona. ¿Sabes cómo obtener un UpdateProgress para mostrar cuando uno de los factores desencadenantes, bueno, se desencadena en esta situación? He intentado colocar UpdateProgress en la página y en el control (fuera del Panel de actualización actual en ambos casos), y en ninguno de los casos aparece. – Andrew

+0

@Andrew; He actualizado mi respuesta con una muestra (para simplificar sin ningún contenido) que funcione para mí. Tiene dos paneles de actualización dentro de un UserControl. Ajústelo a sus requisitos. –

+0

¡Gracias por la ayuda! – Andrew

Cuestiones relacionadas