2

我发现点击浏览器上的“刷新”按钮会暂时搞砸 UpdatePanel 中控件的 ViewState。

这是我的情况:我制作了一个自定义 WebControl,将值存储在 ViewState 中。我将此控件放在 UpdatePanel 中。当我点击浏览器上的“刷新”按钮时,它会暂时清除 ViewState 中的值。然而,在下一次回发时,我点击“刷新”之前 ViewState 中的值神奇地重新出现。

这种行为搞砸了我的网络控制。在我点击“刷新”后,控件返回到其初始状态,因为 ViewState 为空且 IsPostBack 设置为 false。但是,当我单击 WebControl 中的一个回发控件时,WebControl 将使用与我点击“刷新”之前 ViewState 中相同的值重新加载。

奇怪的是,这只发生在我使用 AJAX 时。当我的控件在 UpdatePanel 之外时,Firefox 会给我它的标准消息,“要显示此页面,Firefox 必须发送将重复之前执行的任何操作(例如搜索或订单确认)的信息(重新发送)(取消) 。” 这很好,因为至少行为是一致的。但是,我绝对必须为这个项目使用 AJAX。

所以这就是我想做的——我想让“刷新”行为保持一致。如果点击“刷新”完全不影响 ViewState,那将是最好的。但是,如果它必须清除 ViewState,那很好,只要 ViewState STAYS 清除即可。这些东西都没有价值消失和重新出现。

哦,是的,这是我的示例代码:

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 MethodControl.SaveViewState Method派生出来的。

于 2008-12-09T23:27:23.933 回答
1

我刚刚重新阅读了您的问题,并意识到我错过了一些东西...

您正在点击浏览器刷新按钮!

这是一个问题吗?是的!

当您点击浏览器上的刷新按钮时会发生什么?它刷新当前页面。如果有回发,它将重新发送帖子数据。

就页面而言,AJAX 回调可能会更新 ViewState,但点击浏览器刷新按钮将重新发布旧的 ViewState。

有一个财富是关于这个问题的讨论,你可以谷歌。

一个非常简单的想法是也许将信息存储在会话状态中。当然,那也可能有它自己的问题。但它可能会实现您的直接目标。

擦除回发历史(以防止重新发布)的提示是再次重定向回同一页面。

于 2008-12-12T13:19:42.043 回答
0

您的 ViewState 没有被保存。SaveViewState 覆盖用于保存 OBJECTS,而不是用于将内容放入 ViewState 包中。ViewState 包已经超出了将内容标记为脏的程度,并且您所做的更改将不会被保留。您需要创建一个对象数组来加载/查看 ViewState 信息。

做 BlackMael 展示的事情。

于 2008-12-09T23:32:40.210 回答