2

ブラウザーの [更新] ボタンを押すと、UpdatePanel 内のコントロールの ViewState が一時的に台無しになることがわかりました。

これが私の状況です: ViewState に値を格納するカスタム WebControl を作成しました。このコントロールを UpdatePanel 内に配置しました。ブラウザの「更新」ボタンを押すと、ViewState の値が一時的に消去されます。ただし、次のポストバックでは、「更新」を押す前に ViewState にあった値が魔法のように再表示されます。

この動作により、Web コントロールが台無しになります。ViewState が空で、IsPostBack が false に設定されているため、[更新] をクリックすると、コントロールは初期状態に戻ります。ただし、WebControl 内のポストバック コントロールの 1 つをクリックすると、WebControl は、[更新] をクリックする前に ViewState にあったのと同じ値で再読み込みされます。

奇妙なことに、これは AJAX を使用している場合にのみ発生します。私のコントロールが UpdatePanel の外側にある場合、Firefox は標準的なメッセージを表示します。 ." 少なくとも動作は一貫しているため、これで問題ありません。ただし、このプロジェクトでは絶対に AJAX を使用する必要があります。

これが私がやりたいことです - 「リフレッシュ」動作を一貫させたいのです。「更新」を押してもViewStateにまったく影響がなければ最高です。ただし、ViewState を一掃する必要がある場合は、ViewState が一掃されたままである限り問題ありません。値が消えて再び現れるものはありません。

そうそう、これが私のコード例です:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace TestControls
{
    public class TestControl : WebControl
    {
        int _clickCount;
        bool _mustUpdate;

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);

            _clickCount = ((int)ViewState["clickCount"]);
            _mustUpdate = ((bool)ViewState["mustUpdate"]);
        }

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

            Controls.Clear();
            ControlCreator();
        }

        private void ControlCreator()
        {
            Label tempLabel = new Label();
            LiteralControl tempLiteral = new LiteralControl("<br/><br/>");
            LinkButton tempLink = new LinkButton();

            tempLink.ID = "testLink";
            tempLink.Text = "Click me!";
            tempLink.Click += new EventHandler(tempLink_Click);

            tempLabel.ID = "testLabel";
            tempLabel.Text = _clickCount.ToString();

            Controls.Add(tempLabel);
            Controls.Add(tempLiteral);
            Controls.Add(tempLink);
        }

        void tempLink_Click(object sender, EventArgs e)
        {
            _clickCount++;
            _mustUpdate = true;
        }

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

            if (_mustUpdate)
            {
                Controls.Clear();
                ControlCreator();

                _mustUpdate = false;
            }
        }

        protected override object SaveViewState()
        {
            ViewState["clickCount"] = _clickCount;
            ViewState["mustUpdate"] = _mustUpdate;

            return base.SaveViewState();
        }
    }
}
4

3 に答える 3

1

次のことを試してください...

    protected override void LoadViewState(object savedState)
    {
        if (savedState != null)
        {
            object[] myState = (object[])savedState;

            if (myState[0] != null) base.LoadViewState(myState[0]);
            if (myState[1] != null) _clickCount = ((int)myState[1]);
            if (myState[2] != null) _mustUpdate = ((bool)myState[2]);
        }
    }

    protected override object SaveViewState()
    {
        object[] allStates = new object[3];

        allStates[0] = base.SaveViewState();
        allStates[1] = _clickCount;
        allStates[2] = _mustUpdate;

        return allStates;
    }

基本的に、MSDNのControl.LoadViewStateメソッドControl.SaveViewStateメソッドから上記のコードを派生させました。

于 2008-12-09T23:27:23.933 に答える
1

私はあなたの質問を読み直して、何かを見逃していることに気づきました...

ブラウザの更新ボタンを押しています!

これは問題ですか?はい!

ブラウザの更新ボタンを押すとどうなりますか? 現在のページを更新します。ポストバックがあった場合は、投稿データを再送信します。

AJAX コールバックは、ページに関する限り ViewState を更新する場合がありますが、ブラウザーの更新ボタンを押すと、古い ViewState が再送信されます。

あなたがグーグルできる問題についての豊富な議論があります.

非常に単純なアイデアの 1 つは、情報をセッション状態に保存することです。もちろん、それにも独自の問題がある可能性があります。しかし、それはあなたの当面の目標を達成するかもしれません。

ポストバックの履歴を消去する (再投稿を防ぐため) ためのヒントは、同じページに再度リダイレクトすることです。

于 2008-12-12T13:19:42.043 に答える
0

ViewState が保存されていません。SaveViewState オーバーライドは、オブジェクトを保存するためのものであり、ViewState バッグに物を入れるためのものではありません。ViewState バッグは、すでに汚いものをマーキングするポイントを超えており、行った変更は永続化されません。ViewState 情報をロード/表示するには、オブジェクト配列を作成する必要があります。

BlackMael が示すことを実行します。

于 2008-12-09T23:32:40.210 に答える