【问题标题】:DropDownList AutoPostback fires when Asynchronous Postback occurrs发生异步回发时触发 DropDownList AutoPostback
【发布时间】:2010-08-26 19:01:16
【问题描述】:

我有一个奇怪的问题。

我有一个页面,上面有 2 个 DropDownLists 和一个自定义 Web 用户控件。自定义 Web 用户控件内部有一个 UpdatePanel,UpdatePanel 中有一个 Ajax Timer 控件,用于定期更新内容列表。

当我“下拉”其中一个 DropDownList 并将鼠标悬停在(而不是单击)一个选项上,而 UpdatePanel 中的 Timer 控件异步回发到服务器时,DropDownList 会“自动回发”到服务器!

我试图弄清楚为什么异步回发会导致 DropDownList 表现得好像我选择/单击了一个选项,以便我可以找到解决此问题的方法。

现在重现这个问题真的很简单。 创建一个名为“TimerUpdatedListing”的 Web 用户控件...这是 Web 用户控件的 ASPX 代码标记:

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

这是 Web 用户控件的 VB.NET 服务器端代码:

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

现在,在一个名为 WebForm1.aspx 的 ASPX 页面中,添加 2 个 DropDownLists 和 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>

这是 WebForm1.aspx 页面的 VB.NET 服务器端代码:

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

谢谢,

-弗林尼

【问题讨论】:

  • 你能发布一些你的代码吗?
  • 说真的很简单。我在一个页面上有 2 个 DropDownLists。我有一个带有 UpdatePanel 的用户控件...在 UpdatePanel 中有一个 Repeater 和一个 Timer 控件(当计时器滴答时更新中继器)...*sigh* 用简单的代码更新我的原始帖子。
  • 您意识到更新面板中的所有内容都会“回发”,对吗?如果您需要挑选出单个控件,我建议您使用 Telerik RadAjaxManager 之类的东西
  • 如果下拉列表在更新面板之外,那么您需要确保您的计时器正在刷新更新面板而不是页面。
  • @rockinthesixstring,我当然意识到更新面板中的所有内容都会被 PostedBack 到服务器。事实上,我意识到“一切”都被发回服务器,这样 asp.net 页面生命周期就可以发生......并且实际上只返回了一部分响应(响应被剥离为仅包含更新面板中的内容)。 DropDownLists 在更新面板之外。

标签: asp.net ajax asp.net-ajax


【解决方案1】:

以下是使用触发器触发更新面板的示例。把 timer.tick 事件作为触发器,看看会发生什么

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

PS:我不认为计时器必须包含在更新面板中。实际上,我在代码隐藏中构建了我的计时器,并将它们一起排除在标记之外。

【讨论】:

  • 感谢您的回复。我不需要为此解决方案使用触发器。回复 PS:您可以在 UpdatePanel 中有一个计时器,您只需要注意计时器控件将每隔 X 毫秒发回服务器,无论最后一个请求是否完成。如果计时器控件在最后一个请求返回到浏览器之前计时/回发,那么您可能会遇到 UpdatePanel “始终更新”的情况。请注意这一点,你会没事的。
【解决方案2】:

我尝试了两种不同的解决方案来解决这个问题。

我做的第一件事是检查 Request.Params("__EVENTTARGET") 看它是否与 DropDownList 匹配。如果匹配,那么我将调用 Response.Redirect() 方法。

例如:

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

我注意到这并不总是有效。有时我在 DropDownList 中选择了一个选项并且重定向不会发生,因为计时器滴答声和选定的索引更改事件同时发生。

所以我采取的第二种方法是检查页面是否处于异步回发到服务器的状态。如果是,那么我知道这是发生了计时器滴答事件并且不应该发生重定向。

例如:

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

这有帮助,并且重定向正确发生的可能性比以前的方法要好;但是,它仍然不是 100%。

-弗林尼

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    相关资源
    最近更新 更多