2011-01-20 17 views
5

Ho una pagina con uno ScriptManager, un elenco a discesa HTML generico (<select>) e un UpdatePanel. UpdatePanel contiene un PlaceHolder (per ora). Durante Page_Load, un numero di controlli utente viene aggiunto a PlaceHolder (in realtà, sono diverse istanze dello stesso controllo utente). Il numero da aggiungere non è noto fino a quando la pagina non viene caricata, quindi devono essere caricati in modo dinamico. L'elenco a discesa è popolato con lo stesso numero di voci di menu, e vi è anche javascript sulla pagina (usando jQuery) per mostrare solo uno dei controlli alla volta a seconda dello stato dell'elenco a discesa.Aggiunta di PostBackTriggers e AsyncPostBackTriggers a UpdatePanel per i comandi di grandchild generati dinamicamente

Ogni controllo utente ha due pulsanti che dovrebbero generare un postback asincrono, un elenco a discesa che dovrebbe generare un postback asincrono su una modifica nel valore selezionato e un pulsante che dovrebbe generare un postback sincrono. Se non stava generando i controlli in modo dinamico, e se ci fosse un solo controllo, la struttura sarebbe qualcosa come:

<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> 

Naturalmente, tutti i controlli all'interno ContentTemplate sarebbe in realtà essere parte di ogni controllo utente.

L'aggiunta dei trigger sul lato server non sembra funzionare perché nessun ControlID sembra aiutare l'UpdatePanel a trovare i controlli rilevanti. Posso utilizzare l'ID del controllo o UniqueID del controllo, e non funziona, ed ottengo un errore lungo le linee di

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

Quindi, mi chiedo se ho bisogno di registrare i trigger nel client invece utilizzare ASP.NET Ajax. Ho trovato this page che fondamentalmente spiega come. Tuttavia, non so come prendere in considerazione l'EventName. Gli esempi che ho visto finora sono stati semplicemente l'aggiunta di clic sui pulsanti, ma non so come gestire l'evento SelectedIndexChanged da DropDownList.

Qualsiasi aiuto qui? Ci sono esempi là fuori che mi sono perso? Ovviamente, non è d'aiuto che il metodo nel collegamento che ho dato sia "non ufficiale", quindi non vedo alcun documento MSDN sull'argomento.

Grazie!

+0

Si sta utilizzando .net framework 4.0? Chiedo perché ora hai più controllo su Control.ClientID: http://msdn.microsoft.com/en-us/library/system.web.ui.control.clientid.aspx –

+0

@Tim No, questo deve essere. NET 3.5 per ora. – Andrew

+0

taggato come 3.5. Vado a dare un'occhiata da vicino più tardi. –

risposta

6

Il mio suggerimento sarebbe quello di estrarre tutti i controlli inclusi questo UpdatePanel da questo UpdatePanel in un UserControl. Definisci gli eventi nel tuo usercontrol che vengono generati quando si fa clic sui pulsanti o quando viene modificato l'indice selezionato di Dropdown. Gestisci questi eventi nella tua pagina che contiene il segnaposto (in un singolo UpdatePanel, condizionale, senza trigger). Chiamare manualmente il metodo di aggiornamento del pannello di aggiornamento principale se si aggiungono UserControls.

Per chiarire ciò che intendo dare un'occhiata al seguente esempio:

Main-pagina 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 che tiene la vostra comandi:

<%@ 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 di UserControl:

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 

In questo modo non avrete problemi con ClientID di.

Aggiunta: Se è necessario accedere ai controlli delle tue UserControls in caso-gestori, utilizzare una delle seguenti due opzioni:

  1. gettato NamingContainer del mittente per il tipo di UserControl: Dim uc As DynamicControls = DirectCast(DirectCast(sender, Control).NamingContainer, DynamicControls)
  2. sostituire tutte le occorrenze di (ByVal sender As Object, ByVal e As System.EventArgs) con (uc as DynamicControls). Su questo modo si aggiunge il riferimento del vostro UserControl per l'evento come parametro e si può accedere alle proprietà pubbliche dalla pagina, fe:

    dim txt1 as String = uc.Text1 
    

Se è stata esposta una proprietà Testo1 nella UserControl:

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

La seconda opzione è il modo più pulito e più leggibile.

Aggiornamento: Secondo il vostro commento: è necessario posizionare l'UpdateProgress nella UserControl all'interno del UpdatePanel che viene aggiornato. Ricordarsi di impostare AssociatedUpdatePanelID correttamente. Ad esempio:

<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

Grazie. Sto eseguendo il debug dell'applicazione, e penso che questo lavori più o meno. Ti capita di sapere come ottenere un UpdateProgress da visualizzare quando uno dei trigger è, beh, attivato in questa situazione? Ho provato a posizionare UpdateProgress nella pagina e nel controllo (al di fuori del UpdatePanel effettivo in entrambi i casi), e in nessuno dei due casi appare. – Andrew

+0

@Andrew; Ho aggiornato la mia risposta con un esempio (per semplificare senza alcun contenuto) che funziona per me. Ha due pannelli di aggiornamento all'interno di un UserControl. Adattalo alle tue esigenze. –

+0

Grazie per l'aiuto! – Andrew

Problemi correlati