【问题标题】:ASP.NET- forcing child/container events to fire before parent onload?ASP.NET - 强制子/容器事件在父加载之前触发?
【发布时间】:2011-02-18 10:58:27
【问题描述】:

我正在开发一个问卷类型的应用程序,其中问题存储在数据库中。因此,我在每个 Page.OnLoad 上动态创建控件。 这就像一个魅力,并且 ViewState 在回发之间保持不变,因为我确保我的动态控件始终具有相同的生成 Control.ID。

除了动态填充问题的用户控件外,我的调查问卷页面还包含一个“状态”部分(也由用户控件封装),它表示调查问卷的状态(选项为“完成”、“已开始”或“进行中”)。如果用户更改调查问卷的状态(即从“进行中”变为“完成”),我需要回发到服务器,因为调查问卷的动态部分的内容取决于所选状态。

无论状态如何,某些问题始终存在,而对于所选状态,其他问题可能根本不存在。关键是,当状态发生变化时,我必须回发到页面并呈现正确的问题集。此外,我需要为那些“始终可用”的问题保留任何用户输入的值。

但是,由于 ASP.NET 中的页面生命周期,“状态”用户控件的 OnLoad 包含从数据库加载正确问题所需的正确状态,直到在“动态问题”之后才会执行' 用户控件已被填充(使用错误/过时的值)。

为了解决这个问题,我从我的“状态”用户控件向主页提出了一个事件,以指示状态已更改。然后主页会在“动态问题”用户控件上引发一个事件。因为当这个事件冒泡时,“动态问题”用户控件已经从数据库中加载了“错误”问题,它首先调用 Controls.Clear。然后它愉快地使用新状态来查询数据库中的“正确”问题,并对每个问题执行 Control.Add()。仅供参考,Control.ID 在回发中是一致的。

这个解决方案有效......有点。确实会呈现所选状态的正确问题集;然而,ViewState 正在为那些“始终可用”的问题而迷失。我猜这是因为“动态问题”用户控件在响应状态更改事件时调用 Controls.Clear。这必须以某种方式终止 ViewState 和我的动态控件之间的关联,即使 Control.ID 是一致的。

这似乎是一个常见的要求,我几乎可以肯定有一种更好、更清晰、更不容易出错的方法来实现这一点。万一它不是很明显,尽管去年使用它,我仍然无法理解 ASP.NET 页面的生命周期。非常感谢任何帮助!

【问题讨论】:

  • 我曾经遇到过这个问题,但我一直没有弄清楚。我最终完全改变了我解决整个问题的方式。我想我把它做成了一个多页的过程,我从来没有对它感到满意。祝你好运。我希望这个问题能得到一个好的答案。
  • 因此,您呈现状态为 A 的页面。然后用户更改为状态 B 并发生回发。在此回发期间,您在加载期间以“错误”状态重新创建动态控件?你说哪个状态是错误的?在页面加载期间,状态应该是 B,这是正确的。这是你看到的吗?

标签: asp.net dynamic events viewstate page-lifecycle


【解决方案1】:

您可以将其更改为仅在 Page_Load 中加载控件(而不确定任何与状态相关的内容),并将控件的特定于状态的呈现移动到 Page_PreRender。

如果用户控件负责加载什么,则动态用户控件可以在其 PreRender 事件(或 DataBind 事件)中从数据库中读取。

我认为问题在于用户控件在加载所有控件并加载视图状态之前尝试读取状态。通过将与状态相关的显示延迟到稍后的页面事件,您可以确保它基于正确的状态。

【讨论】:

  • 今晚我试试看。
【解决方案2】:

我确保我的动态控件 总是有相同的生成 控件.ID

ViewState 不受控件 ID 的影响。如果您想在动态控件中处理用户数据输入的 OnClick 事件,则必须在 RaisPostBackEvent 事件之前恢复控件层次结构的结构,该事件在 Page_load 之后立即触发。

如果您想将具有相同状态的动态控件保存在页面上的其他位置,或者您希望在创建其他动态控件后访问控件您必须保存控件层次结构

所以!在一个容器中创建动态控件的第一部分,并在另一个容器中创建回发控件。

例如在您呈现的页面请求中:

< asp:placeholder id="iHaveToBeDuringAllRequests1" >
  First dynamic cintrols
< /asp:placeholder >
< asp:placeholder id="iHaveToBeDuringAllRequests2" >
  Empty on first request 
< /asp:placeholder >

在 PostBack 上渲染:

< asp:placeholder id="iHaveToBeDuringAllRequests1" >
  First dynamic cintrols(you can clear or do not load these controls if you don't need it)
< /asp:placeholder >
< asp:placeholder id="iHaveToBeDuringAllRequests2" >
  Second dynamic controls load here
< /asp:placeholder >

最后一个提示:

我确保我的动态控件 总是有相同的生成 控件.ID

您需要确保通过动态控件正确触发 RaisPostBackEvent(OnClick 等)(您可以使用 INamingContainer 容器而不是占位符)。

【讨论】:

    【解决方案3】:

    Hmm - ASP.NET 页面生命周期;我的最爱之一:)

    我猜这是因为 “动态问题”用户控制调用 Controls.Clear 响应时清除 状态改变事件。这必须 以某种方式杀死之间的联系 ViewState 和我的动态控件, 即使 Control.ID 是 一致。

    听起来这是从视图状态(包括“始终在线”问题)重新创建所有内容,然后将其扔进垃圾箱。 之后 控件被重新创建(没有任何视图状态,因为它的重新创建已经完成)。所以是的,我也认为Controls.Clear 是您丢失视图状态的原因。

    这可能不是一个单行的解决方案。我可以想象不同的方法。

    但是,由于页面生命周期在 ASP.NET,“状态”用户控件 OnLoad,其中包含正确的 加载权限所需的状态 来自数据库的问题,没有得到 执行到'动态 问题的用户控制已经 已填充(错误/陈旧 值)。

    “OnLoad 包含正确的状态”是什么意思?我想说应该可以在动态问题“数据绑定”期间从状态控件中获取“当前选择”(如果您在动态问题控件中碰巧有这样的东西)。 /me 认为这是因为“数据绑定”(在父项中)发生在下面提供的文章“The ASP.NET Page Life Cycle”中提到的第 3 点之后。因此,如果您的动态问题控件知道它必须尊重的状态,它应该能够获取它。如果这不起作用,我会首先检查问题是否出在状态控制中。如果您的动态问题控件不知道任何状态,这显然不起作用。

    另一种方法是让您的动态问题控制不删除它的所有子项 (Controls.Clear),而只删除那些不再需要的问题。您可以(并且我认为您应该)在 PreRender 中执行此操作。因此,为动态问题控制提供一种方法以将“始终在线”问题与其他问题区分开来可能会有所帮助。然后你可以坚持你当前的策略和事件。

    如果您想更深入地了解 ASP.NET 页面生命周期和视图状态并且还不知道它们,这两个链接可能会提供有价值的信息。

    The ASP.NET Page Life CycleTRULY Understanding ViewState

    如果不是很明显,我 无法理解 ASP.NET 页面生命周期,尽管使用 去年的。

    如果你找到有的人请告诉我:)

    【讨论】:

    • 哈哈太对了! Lifecycle 和 ViewState 在我看来是 ASP.NET 中最困难的部分。
    【解决方案4】:

    但是,由于页面生命周期在 ASP.NET,“状态”用户控件 OnLoad,其中包含正确的 加载权限所需的状态 来自数据库的问题,没有得到 执行到'动态 问题的用户控制已经 已填充(错误/陈旧 值)。

    如果知道底层状态控件的client id,就可以绕过web表单,直接访问发布的表单数据,在页面生命周期的任意时刻获取发布的值:

    // where 'selectedStatus' is the id of the html <input> control the user clicks
    string statusString = Request.Form["selectedStatus"];
    

    【讨论】:

    • 微软似乎不喜欢人们这样做,但我发现它真的很有用。作为附加帮助,控件的 UniqueID 属性对应于控件上生成的“名称”属性,因此您可以使用它从 PostData 集合中提取值。
    • 这个解决方案应该在由客户端逻辑的特殊性决定的紧要关头使用。在这种情况下,它会破坏逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    相关资源
    最近更新 更多