动态创建的控件和 ASP.NET 页面生命周期
我正在开发一个 ASP.NET 项目,其中绝大多数表单都是在运行时动态生成的(表单定义存储在数据库中以实现可定制性)。因此,每次 OnLoad 触发时,我都必须动态创建控件并将其添加到页面,而不管 IsPostBack。这一直工作得很好,.NET 负责管理这些控件的 ViewState。
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
RenderDynamicControls()
}
private void RenderDynamicControls()
{
//1. call service layer to retrieve form definition
//2. create and add controls to page container
}
我有一个新的要求,如果用户单击给定的按钮(该按钮是在设计时创建的),则应该以稍微不同的方式重新呈现页面。因此,除了在 OnLoad 中执行的代码(即 RenderDynamicControls())之外,我还有以下代码:
protected void MyButton_Click(object sender, EventArgs e)
{
RenderDynamicControlsALittleDifferently()
}
private void RenderDynamicControlsALittleDifferently()
{
//1. clear all controls from the page container added in RenderDynamicControls()
//2. call service layer to retrieve form definition
//3. create and add controls to page container
}
我的问题是,这真的是实现我所追求的目标的唯一方法吗?仅仅为了响应按钮点击而有效地渲染表单两次似乎是很困难的。我从我的研究中得知,这就是 ASP.NET 中页面生命周期的工作方式:即,在调用子事件之前,OnLoad 必须在每次回发时触发。不过,在喝这杯饮料之前,还是值得先咨询一下 SO 社区。
与此相关的是,一旦我完成了此功能,我计划在页面上放置一个 UpdatePanel 以通过 Ajax 执行页面更新。任何使转换更容易的代码/建议将不胜感激。
I'm working on an ASP.NET project in which the vast majority of the forms are generated dynamically at run time (form definitions are stored in a DB for customizability). Therefore, I have to dynamically create and add my controls to the Page every time OnLoad fires, regardless of IsPostBack. This has been working just fine and .NET takes care of managing ViewState for these controls.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
RenderDynamicControls()
}
private void RenderDynamicControls()
{
//1. call service layer to retrieve form definition
//2. create and add controls to page container
}
I have a new requirement in which if a user clicks on a given button (this button is created at design time) the page should be re-rendered in a slightly different way. So in addition to the code that executes in OnLoad (i.e. RenderDynamicControls()), I have this code:
protected void MyButton_Click(object sender, EventArgs e)
{
RenderDynamicControlsALittleDifferently()
}
private void RenderDynamicControlsALittleDifferently()
{
//1. clear all controls from the page container added in RenderDynamicControls()
//2. call service layer to retrieve form definition
//3. create and add controls to page container
}
My question is, is this really the only way to accomplish what I'm after? It seems beyond hacky to effectively render the form twice simply to respond to a button click. I gather from my research that this is simply how the page-lifecycle works in ASP.NET: Namely, that OnLoad must fire on every Postback before child events are invoked. Still, it's worthwhile to check with the SO community before having to drink the kool-aid.
On a related note, once I get this feature completed, I'm planning on throwing an UpdatePanel on the page to perform the page updates via Ajax. Any code/advice that make that transition easier would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从 Dirk 到 Dirk :-)
RenderDynamicControls 是什么意思?创建并设置控件?如果这是您的意图,则不是 ASP.NET 正在管理您的 ViewState,而是您在管理。如果您在每次加载时填充控件,那么您总是会覆盖现有的 ViewState!
如果要使用 ViewState,请在页面初始化事件中创建控件并将其填充到加载事件中,但前提是请求不是回发。这是必要的,因为 ASP.NET 在 init 和 load 之间重新创建 ViewState。这也是您描述的两个“渲染周期”的原因。您需要第一个控件创建周期,因为如果没有适当的控件集,ASP.NET 就无法恢复 ViewState,并且没有它,ASP.NET 就无法对您的响应做出正确的反应。
回到您的代码:一般来说,您的 RenderDynamicControlsALittleDifferently 不起作用 - 因为您在页面生命周期中太晚创建控件,并且您会通过向控件集合插入新对象来损坏 ViewState。在类似的情况下,我通过将页面重定向到自身(Response.Redirect)解决了这个问题。在这种情况下,RenderDynamicControls 将根据您更改内部状态后的“略有不同的情况”来完成这项工作。
From Dirk to Dirk :-)
What do you mean with RenderDynamicControls? Create and set controls? If this is your intention not ASP.NET is managing your ViewState, but you do. If you fill the controls on every load, you always overwrite the existing ViewState!
If you want to use the ViewState, create your controls in the pages init event and fill them in the load event, but only if the request isn’t a postback. This is necessary, because ASP.NET recreates the ViewState between init and load. And this is also the reason for the two “rendering cycles” you describe. You need the first control creation cycle because ASP.NET can’t restore the ViewState without a proper control set and ASP.NET can’t react proper on your response without it.
Back to your code: In general your RenderDynamicControlsALittleDifferently wouldn’t work - because you create your controls too late in the pages life cycle and you would damage the ViewState by inserting new objects to the control collection. In a similar situation I solved this problem by a redirecting the page to itself (Response.Redirect). In this case RenderDynamicControls would do the job, based on a “little differently situation” after you change your internal state.