1

为了简单起见,我在 ASP.NET 表单中有一个下拉列表和一个按钮。下拉列表有一个调用 DropDownList1_SelectedIndexChanged 的​​自动回发函数,并且页面被重定向到某个地方(例如 www.google.com),并且按钮具有转到 Button1_Click1 的 onclick 并且页面被重定向到 www.yahoo.com。

问题:如果我点击按钮,我会转到 Yahoo,这正是您所期望的。如果我在浏览器中单击后退按钮并选择下拉列表,我会转到 Google,这也是正确的,但是如果我单击后退按钮然后单击该按钮,我会被重定向到 Google。呃?为什么不去雅虎?

这是我的代码:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="test.aspx.cs" Inherits="test" %>

<!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>Testing Auto-Postback</title>
</head>
<body>
    <form id="form1" runat="server">

                <asp:DropDownList ID="DropDownList1" runat="server" onselectedindexchanged="DropDownList1_SelectedIndexChanged" AutoPostBack="true" ValidationGroup="form1">
                <asp:ListItem>Please select</asp:ListItem>
                <asp:ListItem>Go to Google</asp:ListItem>
                </asp:DropDownList>

                <hr />

                <asp:Button ID="Button1" runat="server" Text="Go to Yahoo" 
                    ValidationGroup="form2" onclick="Button1_Click1" />
    </form>
</body>
</html>

代码背后:

using System;

public partial class test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Response.Redirect("http://www.google.com");
    }

    protected void Button1_Click1(object sender, EventArgs e)
    {
        Response.Redirect("http://www.yahoo.com");
    }
}

如果有人可以帮助我,将不胜感激。

4

1 回答 1

1

好吧,经过一番挖掘,我发现了以下内容:

当我们单击 时Button,直到Button1_Click1事件被引发的页面生命周期是这样的:

Begin PreInit
End PreInit
Begin Init
End Init
Begin InitComplete
End InitComplete
Begin LoadState
End LoadState
Begin ProcessPostData
End ProcessPostData
Begin PreLoad
End PreLoad
Begin Load
End Load
Begin ProcessPostData Second Try
End ProcessPostData Second Try
Begin Raise ChangedEvents
End Raise ChangedEvents
Begin Raise PostBackEvent
Raised Button1_Click1 // Button event here

现在,当我们更改 时DropDownList,直到DropDownList1_SelectedIndexChanged引发事件的页面生命周期是这样的:

Begin PreInit
End PreInit
Begin Init
End Init
Begin InitComplete
End InitComplete
Begin LoadState
End LoadState
Begin ProcessPostData
End ProcessPostData
Begin PreLoad
End PreLoad
Begin Load
End Load
Begin ProcessPostData Second Try
End ProcessPostData Second Try
Begin Raise ChangedEvents
Raised DropDownList1_SelectedIndexChanged // DropDownList event here

分析两个页面生命周期,我们看到DropDownList1_SelectedIndexChanged事件是在页面“ChangedEvents”过程中引发的,此方法发生在引发Button1_Click1事件的页面“PostBackEvent”过程之前。

现在,当您更改DropDownListSelectedIndex 时,您将被重定向到 Google。当您点击后退按钮时,浏览器会检索该页面的最后一个状态,这意味着该页面DropDownList将保持您之前更改的值。如果在该阶段单击按钮,则DropDownList和 Button 都将根据请求值发送。由于DropDownList首先引发事件,页面会再次重定向到 Google。

更新:

一种解决方法可以在后面的代码上实现以下内容:

public partial class test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        if (IsPostBack)
        {
            //If the form is posting the button, it means you clicked it
            bool isButtonPostBackEvent = Request.Form.AllKeys.Contains(Button1.UniqueID);

            //Gets the posted value of the DropDownList
            string selectedValue = Request.Form[DropDownList1.UniqueID];

            //Retrieves the index of the DropDownList postedValue
            int valueIndex = DropDownList1.Items.IndexOf(DropDownList1.Items.FindByValue(selectedValue));

            //Verify if posted value of the dropdownlist is different from the server (will raise the SelectedIndexChangedEvent event)
            bool willRaiseSelectedIndexChangedEvent = DropDownList1.SelectedIndex != valueIndex;

            //Verifies if both events will be fired, so apply the button
            //behavior, otherwise let the asp.net do its 
            //magic and raise the events automatically
            if (isButtonPostBackEvent && willRaiseSelectedIndexChangedEvent)
            {
                RedirectToYahoo();
            }
        }
    }

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        RedirectToGoogle();
    }

    protected void Button1_Click1(object sender, EventArgs e)
    {
        RedirectToYahoo();
    }

    private void RedirectToGoogle()
    { 
        Response.Redirect("http://www.google.com");
    }

    private void RedirectToYahoo()
    { 
        Response.Redirect("http://www.yahoo.com");
    }
}

在 OnInit 事件上,代码标识将由 asp.net 引发的事件。当两个事件都存在时,我们应用按钮单击行为,因为在这种情况下它具有优先级(它被单击)。

如果你不介意,你也可以做得更简单:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    if (IsPostBack)
    {
        bool isButtonPostBackEvent = Request.Form.AllKeys.Contains(Button1.UniqueID);

        if (isButtonPostBackEvent)
        {
            RedirectToYahoo();
        }
    }
}
于 2012-10-27T13:18:04.223 回答