ASP.Net:为什么我在后续回发中可用的控件事件中对Viewstate所做的更改?

时间:2009-02-24 19:19:49

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

我正在使用ASP.Net AJAX在ASP.Net 3.5 WebForms中编写自定义控件。我正在建立一个状态切换到控件(扩展和折叠模式)。我一直在尝试在ViewState中保持控件的当前状态,手动在服务器端事件处理程序中更改它:

object oExpanded = ViewState[ "Expandedness" ];
if(oExpanded == null)
{
    oExpanded = ListState.Collapsed;
}
ListState lsCurrentState = (ListState) oExpanded;
if(lsCurrentState == ListState.Collapsed)
{
    //code snipped - move to expanded mode here
    ViewState[ "Expandedness" ] = ListState.Expanded;
}
else
{
    //code snipped - move to collapsed mode here
    ViewState[ "Expandedness" ] = ListState.Collapsed;
}

我认为这不重要,但实际渲染发生在updatepanel中,上面的代码位于异步触发的事件处理程序中。我遇到的问题是,在下一个回发中,ViewState["Expandedness"]返回null。我曾尝试使用Fritz Onion的Viewstate Decoder工具查看回发之间viewstate的实际内容,但它告诉我序列化数据无效。

我在这里采取了错误的做法吗?什么是解决这个问题的正确方法?

3 个答案:

答案 0 :(得分:1)

你说它在UpdatePanel中是可以的 - 这应该没有任何区别。

我怀疑ViewState是为您的控件或其父母之一禁用的:如果禁用任何父级(一直到页面),它将被禁用为您的控件。

为了解决这个问题,你可以使用页面的ViewState字典而不是你控制的字典。

即。而不是说:

this.ViewState[ "Expandedness" ] = ListState.Expanded;

说:

this.Page.ViewState[ "Expandedness" ] = ListState.Expanded;

如果页面上有多个控件实例,则需要确保ViewState键是唯一的,可能是这样的:

this.Page.ViewState[ this.ClientID + "Expandedness" ] = ListState.Expanded;

作为替代方案(即使ViewState已禁用该页面也可以使用),您可以考虑将Expandedness存储在ControlState中。它有点棘手,但谷歌它,你会很快找到一个代码示例。建议您只在ControlState中存储绝对最少的信息,但是像这样的单个标记很好(实际上是它的设计目的)。

答案 1 :(得分:0)

你什么时候打电话给这个代码?如果在Page_Init中调用它太早了,你对视图状态所做的任何更改都将被忽略。

只是一个想法

答案 2 :(得分:0)

进一步调查:我在子控件事件处理程序中对Viewstate所做的更改与Page_Prerender一样长(即在页面的事件生命周期中稍后),所以问题不在于Viewstate没有得到写给。但是对页面的任何后续回发 - 同步或异步 - 都不会在viewstate中显示该值。