2010-08-26 6 views
0

Eh bien, j'ai un problème étrange.DropDownList AutoPostback se déclenche lorsque des occurrences asynchrones Postback

J'ai une page avec 2 DropDownLists dessus et un contrôle d'utilisateur Web personnalisé. Le contrôle d'utilisateur Web personnalisé a un UpdatePanel en lui, et un contrôle Ajax Timer dans le UpdatePanel pour mettre à jour périodiquement une liste de choses.

Lorsque je "drop-down" l'une des DropDownLists et survolez (ne cliquez pas sur) une option alors que le contrôle Timer dans le UpdatePanel publie de manière asynchrone sur le serveur, le DropDownList "autopostbacks" sur le serveur! J'essaie de comprendre pourquoi une publication asynchrone entraînerait le DropDownList à agir comme si j'avais sélectionné/cliqué sur une option afin que je puisse contourner ce problème.

Maintenant, c'est très simple de reproduire ce problème. Créer un contrôle utilisateur Web appelé « TimerUpdatedListing » ... c'est le balisage de code ASPX pour le contrôle utilisateur Web:

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="TimerUpdatedListing.ascx.vb" Inherits="MyNamespace.TimerUpdatedListing" %> 
<div style="width: 150px; height: 150px; overflow: auto; border: solid 1px navy;"> 
    <asp:UpdatePanel ID="anUpdatePanel" runat="server"> 
     <ContentTemplate> 
      <asp:Repeater ID="aRepeater" runat="server"> 
       <ItemTemplate> 
        <div style="border-bottom: solid 1px #EEC900; margin: 3px; padding: 2px;"> 
         Id: 
         <%#Eval("Id")%> 
         <br /> 
         Time: 
         <%#Eval("Time")%> 
        </div> 
       </ItemTemplate> 
      </asp:Repeater> 
      <asp:Timer ID="aTimer" runat="server" Interval="2000"> 
      </asp:Timer> 
     </ContentTemplate> 
    </asp:UpdatePanel> 
</div> 

Ceci est le code côté serveur VB.NET pour le contrôle utilisateur Web:

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

    Private _aListOFThings As List(Of Things) 

    Private Sub aTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles aTimer.Tick 
     If Session("_aListOfThings") Is Nothing Then 
      _aListOFThings = New List(Of Things) 
     Else 
      _aListOFThings = CType(Session("_aListOfThings"), List(Of Things)) 
     End If 

     If _aListOFThings.Count > 9 Then 
      _aListOFThings = New List(Of Things) 
     End If 

     _aListOFThings.Add(New Things((_aListOFThings.Count + 1).ToString, Now.ToString("hh:mm:ss"))) 
     Session("_aListOfThings") = _aListOFThings 
     aRepeater.DataSource = _aListOFThings 
     aRepeater.DataBind() 
    End Sub 

    Private Class Things 
     Private _time As String 
     Private _id As String 
     Public Property Time() As String 
      Get 
       Return _time 
      End Get 
      Set(ByVal value As String) 
       _time = value 
      End Set 
     End Property 
     Public Property ID() As String 
      Get 
       Return _id 
      End Get 
      Set(ByVal value As String) 
       _id = value 
      End Set 
     End Property 
     Public Sub New(ByVal id As String, ByVal time As String) 
      _id = id 
      _time = time 
     End Sub 
    End Class 
End Class 

maintenant, dans une page ASPX appelée WebForm1.aspx, ajoutez 2 DropDownLists et le contrôle utilisateur Web:

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="MyNamespace.WebForm1" %> 

<%@ Register Src="TimerUpdatedListing.ascx" TagName="TimerUpdatedListing" TagPrefix="uc1" %> 
<!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>Test</title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <asp:ScriptManager ID="ScriptManager1" runat="server"> 
     </asp:ScriptManager> 
     <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true"> 
      <asp:ListItem Text="1" Value="1" /> 
      <asp:ListItem Text="2" Value="2" /> 
      <asp:ListItem Text="3" Value="3" /> 
      <asp:ListItem Text="4" Value="4" /> 
      <asp:ListItem Text="5" Value="5" /> 
     </asp:DropDownList> 
     <asp:Label ID="selectedValue1" runat="server"></asp:Label> 
     <br /> 
     <asp:DropDownList ID="DropDownList2" runat="server" AutoPostBack="true"> 
      <asp:ListItem Text="a" Value="a" /> 
      <asp:ListItem Text="b" Value="b" /> 
      <asp:ListItem Text="c" Value="c" /> 
      <asp:ListItem Text="d" Value="d" /> 
      <asp:ListItem Text="e" Value="e" /> 
     </asp:DropDownList> 
     <asp:Label ID="selectedValue2" runat="server"></asp:Label> 
     <br /> 
     <br /> 
     <uc1:TimerUpdatedListing ID="TimerUpdatedListing1" runat="server" /> 
    </div> 
    </form> 
</body> 
</html> 

Voici le code côté serveur VB.NET pour le WebForm1.aspx page:

Public Partial Class WebForm1 
    Inherits System.Web.UI.Page 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
     If String.IsNullOrEmpty(Request.Params("ddl1")) = False Then 
      selectedValue1.Text = Request.Params("ddl1") 
     End If 
     If String.IsNullOrEmpty(Request.Params("ddl2")) = False Then 
      selectedValue2.Text = Request.Params("ddl2") 
     End If 
    End Sub 

    Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged 
     Response.Redirect(Request.Url.LocalPath + "?ddl1=" + DropDownList1.SelectedValue.ToString, True) 
    End Sub 

    Private Sub DropDownList2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList2.SelectedIndexChanged 
     Response.Redirect(Request.Url.LocalPath + "?ddl2=" + DropDownList2.SelectedValue.ToString, True) 
    End Sub 
End Class 

Merci,

-Frinny

+0

pouvez-vous poster un peu de votre code? –

+0

Sérieusement c'est très simple. J'ai 2 DropDownLists sur une page. J'ai un contrôle d'utilisateur avec un UpdatePanel ... dans le UpdatePanel il y a un répéteur et un contrôle de minuterie (le répéteur est mis à jour quand la minuterie fonctionne) ... * soupir * Mise à jour de mon article original avec un code simple. – Frinavale

+0

vous vous rendez compte que tout ce qui se trouve dans un panneau de mise à jour est "posté" correctement? Si vous avez besoin de sélectionner des contrôles individuels, je vous recommande d'utiliser quelque chose comme le [Telerik RadAjaxManager] (http://demos.telerik.com/aspnet-ajax/ajax/examples/manager/firstlook/defaultcs.aspx) –

Répondre

0

J'ai essayé deux solutions différentes à ce problème.

La première chose que j'ai faite a été de vérifier le Request.Params ("__ EVENTTARGET") pour voir si elle correspondait à DropDownList. Si cela correspond, j'appellerais la méthode Response.Redirect().

Par exemple:

Public Partial Class WebForm1 
    Inherits System.Web.UI.Page 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
     If String.IsNullOrEmpty(Request.Params("ddl1")) = False Then 
      selectedValue1.Text = Request.Params("ddl1") 
     End If 
     If String.IsNullOrEmpty(Request.Params("ddl2")) = False Then 
      selectedValue2.Text = Request.Params("ddl2") 
     End If 
    End Sub 

    Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged 
     Dim ctrlNameThatCausedPostback As String = Request.Params("__EVENTTARGET") 
     If String.IsNullOrEmpty(ctrlNameThatCausedPostback) = False AndAlso Page.FindControl(ctrlNameThatCausedPostback) Is DropDownList1 Then 
      Response.Redirect(Request.Url.LocalPath + "?ddl1=" + DropDownList1.SelectedValue.ToString, True) 
     End If 
    End Sub 

    Private Sub DropDownList2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList2.SelectedIndexChanged 
     Dim ctrlNameThatCausedPostback As String = Request.Params("__EVENTTARGET") 
     If String.IsNullOrEmpty(ctrlNameThatCausedPostback) = False AndAlso Page.FindControl(ctrlNameThatCausedPostback) Is DropDownList2 Then 
      Response.Redirect(Request.Url.LocalPath + "?ddl2=" + DropDownList2.SelectedValue.ToString, True) 
     End If 
    End Sub 
End Class 

je remarquai que cela ne fonctionne pas toujours. Il y avait des moments où j'ai choisi une option dans le DropDownList et la redirection ne se produirait pas parce que la coche de temporisateur et l'événement changé d'index choisi se sont produits en même temps. Donc la deuxième approche que j'ai prise était de vérifier si la page est dans un postback asynchrone au serveur. Si c'était le cas, alors je savais que c'était l'événement tick tick qui avait lieu et que le Redirect ne devait pas se produire.

Par exemple:

Public Partial Class WebForm1 
    Inherits System.Web.UI.Page 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
     If String.IsNullOrEmpty(Request.Params("ddl1")) = False Then 
      selectedValue1.Text = Request.Params("ddl1") 
     End If 
     If String.IsNullOrEmpty(Request.Params("ddl2")) = False Then 
      selectedValue2.Text = Request.Params("ddl2") 
     End If 
    End Sub 

    Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged 
     If ScriptManager.GetCurrent(Me.Page).IsInAsyncPostBack = False Then 
      Response.Redirect(Request.Url.LocalPath + "?ddl1=" + DropDownList1.SelectedValue.ToString, True) 
     End If 
    End Sub 

    Private Sub DropDownList2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList2.SelectedIndexChanged 
     If ScriptManager.GetCurrent(Me.Page).IsInAsyncPostBack = False Then 
      Response.Redirect(Request.Url.LocalPath + "?ddl2=" + DropDownList2.SelectedValue.ToString, True) 
     End If 
    End Sub 
End Class 

Cela a permis, et la probabilité que le Redirect se produirait bien était mieux que l'approche précédente; Cependant, ce n'est toujours pas 100%.

-Frinny

0

Voici un exemple d'utilisation des déclencheurs pour déclencher votre panneau de mise à jour. Mettez l'événement timer.tick comme déclencheur et voir ce qui se passe

http://www.asp.net/ajax/tutorials/understanding-asp-net-ajax-updatepanel-triggers

PS: Je ne pense pas que la minuterie doit être inclus dans le panneau de mise à jour. En fait, je construis mes timers dans le codebehind et je les garde tous hors du balisage.

+0

Merci pour votre réponse. Je n'ai pas besoin d'utiliser de triggers pour cette solution. Répondre à PS: Vous pouvez avoir une minuterie dans un UpdatePanel. Vous devez simplement savoir que le contrôle de minuterie sera renvoyé au serveur toutes les X millisecondes, que la dernière requête soit terminée ou non. Si le contrôle de minuterie ticks/postsback avant que la dernière demande est retournée au navigateur, alors vous pourriez rencontrer une situation où le UpdatePanel est "toujours à jour". Soyez conscient de cela et tout ira bien. – Frinavale

Questions connexes