2010-06-11 76 views
21

我在页面的viewstate中存储了一个对象。现在,当我访问usercontrol上的相同视图对象时,它显示为空。我甚至尝试在usercontrol和page中使用相同的名称创建相同的viewstate。两者具有不同的值。为什么我无法访问usercontrol中的页面viewstate?

我知道viewstate是一个受保护的属性。这个东西是如何在上面的scenerio中实现的,或者是否有任何其他原因导致这种行为。

编辑:

用户控件存在于页面的标记。我没有动态加载它。

我有一个页面EditFacilityworkType.aspx。在页面上我有一个用户控件FacilityWorkTypeDetails.aspx(FacilityWorkTypeDetails1)。在这个usercontrol里面我有一个用户控件Workflow.aspx(Workflow1)

Page_Load()of Page 我正在检索页面page_load()上的workflowdetails。

FacilityWorktype facilityWorkType = facilityDetails.GetFacilityWorktypeDetail(SessionHelper.FacilityWorkTypeID); 
ViewState["WorkFlow"] = facilityWorkType.FacilityWorkTypeWorkFlow 

Inside usercontrol FacilityWorkTypeDetails.aspx。我有一个属性

public FacilityWorktype FacilityWorkTypeDetails 
{ 
    get 
    { 
     #region Fill FacilityWorktype 
     return GetEntityFromControl(); 
     #endregion 
    } 
    set 
    { 
     PopulateControls(value); 
    } 
} 

现在我在页面的页面加载设置该属性

FacilityWorkTypeDetails1.FacilityWorkTypeDetails = facilityWorkType; 

里面Workflow.aspx,我有一个属性

/// <summary> 
/// Property to fill entity object from controls on this page 
/// </summary> 
public WorkFlow WorkFlowDetails 
{ 
    get 
    { 
     return GetEntityFromControls(); 
    } 
    set 
    {    
     BindTranscriptionMethodDDL(ddlTranscMethod); 
     PopulateControls(value); 
    } 
} 

现在PopulateControls()FacilityWorkTypeDetails1的,我正在设置工作流程的属性1

private void PopulateControls(Facility Worktype值) {

Workflow1.WorkFlowDetails = value.FacilityWorkTypeWorkFlow; 
} 

现在,当我从

private WorkFlow GetEntityFromControls() 
{ 
    WorkFlow workFlow = (ViewState["WorkFlow"] as WorkFlow) ?? new WorkFlow(); 
    //workFlow is null 

} 

检索值那么现在这个函数内部工作流程为空。我想问,为什么当我在页面中设置viewstate时为空。

+2

如何(或其中;后面的代码)你“在视图状态页面上存储的对象”?如果你需要存储“某处”“某处”以便稍后从“其他地方”检索它,那么你似乎在寻找会话功能而不是视图状态......而且你不能“创建相同的视图状态”:你是什么意思; viewstate由ASP.NET自动维护(创建等)?我认为你在这里混合了一些东西(最可能是视图状态和会话)。如果你描述你正在努力达到的目标,这可能会有所帮助。 – scherand 2010-06-11 08:22:55

+0

您是否检查您的页面或web.config中的enableviewstate是否设置为false? – mamoo 2010-06-11 08:24:15

+2

我还没有完全理解你想要达到的目标。 **但我想我可以回答你为什么'workFlow'为null **的问题。 “问题”是'GetEntityFromControls()'在“Workflow.aspx”内部(而不是'Workflow.ascx'可能?)。所以你访问的'ViewState'对象不是'Page'中的一个。所以严格来说,'ViewState [“WorkFlow”]'不是空的,但没有定义/可用(在'ViewState'对象中没有称为“WorkFlow”的条目,因为没有人在其中放置过)。 – scherand 2010-06-11 09:10:31

回答

36

Scherand在这里非常正确。我想补充一下他带给桌上的东西。

从System.Web.UI.Control派生的每个控件都具有ViewState属性。这个属性是一个StateBag集合。 Control的每个实例都有自己的ViewState StateBag,所以Scherand提到过,ViewState对于控件来说是唯一的。当页面被渲染时,页面的整个Control树被迭代,所有的ViewState集合被合并到一个树状结构中,并且最终的结构被序列化为一个字符串并呈现给页面。

由于ViewState属性被标记为受保护,因此无法使用反射从用户控件访问Page的ViewState。

但是,诚实地说,您应该放弃使用ViewState作为数据存储介质。这里有一些原因:

  1. ViewState被渲染并输出到客户端浏览器。维护集合中的数据对象会扩大页面的输出。
  2. 除非在ViewState上启用了加密,否则呈现给客户端浏览器的编码字符串可以手动解码,任何人都可以访问数据对象的内容。这是一个相当重要的安全漏洞。

这听起来像是你想要做的就是在页面和用户控件之间共享数据。在控件之间共享数据的最佳方式是使用“Items”集合(这是HttpContext类的属性)。集合是一个Hashtable,可以从你的页面和用户控件,像这样来访问:

Context.Items["Workflow"] = workflowInstance; 

使用这种技术的最好的部分是,它不产生任何额外的开销或臃肿的页面输出。 Items集合存在于单个HTTP请求的上下文中。这意味着当您的请求完成并且您的页面输出已呈现给客户端浏览器时,Items集合将从服务器内存中清除。它是ASP.NET中临时数据存储的理想媒介。

现在,如果您希望数据对象保持不仅仅是当前请求的可访问性,您最好将它存储在Session中。

+0

感谢这个答案,这正是我一直在寻找的! – Peter 2010-11-12 11:08:23

+0

在回发上怎么样?我的代码:Context.Items [“dtCountryRecords”] = dtCountry;但是当我第一次访问它时,它给了我正确的值,但是在回发函数中,在usercontrol pageload事件中返回null。 – user1254053 2015-05-14 11:34:54

+0

“Items”集合无法在Postback中生存。请看上面我回答的最后一段,以获得更多细节。 如果你想要一个能够存活的媒体回传,你需要看看“Session”或“Cache”集合。 – 2015-06-01 16:22:22

1

在回发上您是否创建了控件?如果后面的代码没有创建ctrl,那么它不会知道它。

仅当这是生成的控件时才适用。您可能需要发布代码和更多信息才能获得答案。

Viewstate是一个怪物,这就是为什么我们很多人都去MVC。

3

我还是不会在这里讨论一切(参见上面的评论)。但我很肯定你是误解ViewState

ViewState是每控制,而不是每个请求或会话或任何。

在你的例子中,考虑一些其他的控件(例如一个标准的ASP.NET控件),由于某种原因决定把一个名字为WorkFlow的东西放到viewstate中。如果你试图做的事情会起作用,这个对象会覆盖你的(或者反过来,你的对象会被另一个覆盖)。

或者我错过了什么?

也许阅读TRULY Understanding ViewState可以帮助您了解视图状态是什么/它是如何工作的(是的,我非常喜欢这篇文章,这就是为什么我一直在发布该链接)。

1

page viewstate是usercontrol可以访问的视图状态的不同状态包。每个控件都有自己的私有视图状态。所以你不能直接从usercontrol代码隐藏中访问页面viewstate。

,你可以用公开的属性或方法视图状态值,然后调用这些属性/方法

相关问题