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' プロシージャでイベントが発生することがわかります。このメソッドは、イベントを発生させるページ 'PostBackEvent' プロシージャよりも前に発生しますButton1_Click1

DropDownListSelectedIndex を変更すると、Google にリダイレクトされます。戻るボタンを押すと、ブラウザはそのページの最後の状態を取得します。つまり、DropDownList前に変更した値のままになります。その段階でボタンをクリックするDropDownListと、 と Button の両方がリクエスト値で送信されます。イベントが最初に発生するDropDownListと、ページは再び Google にリダイレクトされます。

アップデート:

回避策の 1 つは、コード ビハインドに以下を実装することです。

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 に答える