【问题标题】:ViewState is not saved across postback the second time the page postsback页面第二次回发时,ViewState 不会跨回发保存
【发布时间】:2009-12-17 19:44:13
【问题描述】:

我有一个 ASP.NET 页面,其中包含一个名为 ReportCtrl 的用户控件(我自己的控件与报告服务等无关)。 ReportCtrl 有一个名为 TreeViewCtrl 的用户控件,其中包含一个 Telerik TreeView 和一些时髦的业务逻辑来显示节点。

TreeView 放置在 ASP.NET AJAX 面板中。当用户单击可检查节点时,它会回传到服务器并将新的 Mapping 对象(标记为 Serializable)保存到存储在 ViewState 中的 List 中。

我遇到的问题是:-

  1. 选中第一个复选框后,项目将保存到列表中,然后添加到 ViewState。
  2. 选中第二个复选框后,项目将保存到列表中,然后添加到 ViewState。
  3. 选中第三个复选框时,加载的 ViewState 中只有 1 个项目。

我已重写以检查 ViewState 中的项目数,并且我可以看到,当检查第二个项目时,SaveViewState 正在使用 3 个项目保存 ViewState。在第三个复选框上调用 LoadViewState 时,我可以看到解码后的 ViewState 中只有一项。

protected override void LoadViewState(object savedState)
protected override object SaveViewState()

不知何故,视图状态仅适用于 1 项,并且仅适用于第一项。

我们已通过删除 Telerik TreeView 并仅在按钮单击事件上手动添加项目来验证这与 Telerik TreeView 无关。我们还通过存储字符串列表来消除该对象。

我们对尝试什么新鲜出炉。有没有人遇到过这个问题?我们可以尝试任何想法吗?

谢谢。

代码

这里是更新面板的代码:

<asp:UpdatePanel runat="server" ID="upnlTreeView" ChildrenAsTriggers="true" 
        RenderMode="Inline" UpdateMode="Conditional" EnableViewState="true">
<ContentTemplate>
    <telerik:RadAjaxManager runat="server" ID="RadAjaxManager1">
        <AjaxSettings>
            <telerik:AjaxSetting AjaxControlID="RadAjaxManager1">
                <UpdatedControls>
                    <telerik:AjaxUpdatedControl ControlID="ClickedNodeLabel" />
                </UpdatedControls>
            </telerik:AjaxSetting>
        </AjaxSettings>
    </telerik:RadAjaxManager>
        <telerik:RadTreeView ID="RadTreeView1" runat="server" Width="100%" Height="420px"
            PersistLoadOnDemandNodes="true" LoadingStatusPosition="BelowNodeText" CausesValidation="false"
            OnClientNodePopulated="nodePopulated" OnClientNodePopulating="nodePopulating" OnClientLoad="onLoad"
            CheckBoxes="true" CheckChildNodes="false" AllowNodeEditing="false" MultipleSelect="false" 
            LoadingMessage="Loading..." AppendDataBoundItems="true" Skin="Vista" EnableViewState="true" 
            onnodecheck="RadTreeView1_NodeCheck"  >

            <ExpandAnimation Type="none" />
            <CollapseAnimation Type="none" />
            <WebServiceSettings Path="/ESConsole/ws/PTService.asmx" Method="GetNodes" />

        </telerik:RadTreeView>

</ContentTemplate>

下面是后面代码中List定义和其他方法的代码:

    public List<ECodeMapping> ECodeMappings
    {
        get
        {
            return (ViewState["__lstECodeMapping"] == null) ? new List<ECodeMapping>()
                : ViewState["__lstECodeMapping"] as List<ECodeMapping>;
        }
        set { ViewState["__lstECodeMapping"] = value; }
    }
    protected override void LoadViewState(object savedState)
    {
        base.LoadViewState(savedState);
        int count1 = (ViewState["__lstECodeMapping"] as List<ECodeMapping>).Count;
    }

    protected override object SaveViewState()
    {
        int count1 = (ViewState["__lstECodeMapping"] as List<ECodeMapping>).Count;
        return base.SaveViewState();
    }
    protected void RadTreeView1_NodeCheck(object sender, RadTreeNodeEventArgs e)
    {
        RadTreeNode node = e.Node;
        int iLevel = node.Attributes["Level"].ToSafeInt();
        if (iLevel == 2)
        {
            var nList = ECodeMappings.FindAll(x => x.DocId == node.Value.ToSafeInt() && x.SecId < 1);
            if (nList.Count() == 0 && node.Checked == true)
            {
                // Add the node if it doesn't exist
                ECodeMapping newMapping = new ECodeMapping { ReportId = ReportId, DocId = node.Value.ToSafeInt(), SecId = int.MinValue };
                ECodeMappings.Insert(0, newMapping);
                return;
            }

【问题讨论】:

  • 一方面你说它只适用于 one 项目,但你在“我一直遇到的问题是”之后的编号列表似乎在说它适用于前 两个 项。它是哪个,当进程失败时哪个项目处于 ViewState 中? (第一个、第二个或第三个节点的数据?)
  • 好的,我看到它仍然有点不清楚。我添加的第一个项目保存得很好。我添加的第二项丢失了。希望能解决这个问题?
  • 请帮忙....我要疯了...

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


【解决方案1】:

UpdatePanel 是否真的将 ViewState 发送到服务器并在更新时替换当前的 ViewState?使用 Fiddler 或类似工具查看实际的 HTTP 流量。我猜您没有为所有更新返回 ViewState。

【讨论】:

  • 感谢您的反馈。它实际上是在获取 Viewstate 信息。
【解决方案2】:

发现问题。

我们在父用户控件中有一个脚本,如下所示:-

错误代码

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(EndRequest);
var postBackElement;
function EndRequest(sender, args) {
    if (postBackElement.id == '<%= btnUpload.ClientID %>')
        var uprog1 = $get('<%= this.UpdateProgress1.ClientID %>');
        if(uprog1 != null)
        {
         uprog1.style.display = 'none';
        }
        $find('<%= mpeProgress.ClientID %>').hide();
}

这个有问题的脚本必须更改为以下内容:-

好代码

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(EndRequest);
var postBackElement = null;
function EndRequest(sender, args) {
    if (postBackElement != null && postBackElement.id == '<%= btnUpload.ClientID %>')
        var uprog1 = $get('<%= this.UpdateProgress1.ClientID %>');
        if(uprog1 != null)
        {
         uprog1.style.display = 'none';
        }
        $find('<%= mpeProgress.ClientID %>').hide();
}

总结

需要检查 postBackElement 是否为空。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多