我试图环绕asp.net我的头。 我有一个背景,很长一段时间PHP开发人员,但现在我面对学习asp.net的任务,我遇到一些麻烦吧。 这很可能是因为我试图强迫东西是不适合的框架 - 所以我想学习如何做“正确的方式”。 :-)
我的问题是如何控件编程在运行时添加到页面。 至于我可以计算出你需要创建在page_init的控件,否则他们在下一回传消失。 但是很多时候,我面临着我不知道它控制在page_init增加,因为它是依赖于值从以前的回发的问题。
一个简单的场景可以用在设计中添加一个下拉控件的窗体。 下拉设置为的AutoPostBack。 当回传发生我需要呈现一个或多个控制denepending上从下拉控制所选择的值,并且优选地具有这些控制充当如果他们被设计中加入(如在“回发的情况下,表现‘正常’)。
我该怎么走上错误的道路吗?
我同意在这里提出的其他要点“如果你能摆脱动态创建控件,那么这样做......”(由@ 加斯帕的Blad简森又名 ),但这里有一个窍门我在过去的工作进行与动态创建的控件。
这个问题就变得鸡与蛋。 你需要你的ViewState创建控件树,你需要你的控件树创建让你的ViewState。 嗯,这是几乎是正确的。 有一种方法在你的浏览状态值来获得的树的其余部分被填充。 这是通过重写LoadViewState(...)
和SaveViewState(...)
在SaveViewState保存您想要创建的控制:
protected override object SaveViewState()
{
object[] myState = new object[2];
myState[0] = base.SaveViewState();
myState[1] = controlPickerDropDown.SelectedValue;
return myState
}
当框架调用你的“LoadViewState”重写你会得到你“SaveViewState”返回的确切对象:
protected override void LoadViewState(object savedState)
{
object[] myState = (object[])savedState;
// Here is the trick, use the value you saved here to create your control tree.
CreateControlBasedOnDropDownValue(myState[1]);
// Call the base method to ensure everything works correctly.
base.LoadViewState(myState[0]);
}
我用这个成功创建,其中一个数据集被序列化到ViewState中存储,允许用户进行多次修改,回送数据更改的整个电网和最后提交他们在一个单一的“保存”所有更改ASP.Net页面操作。
您必须添加控件的OnInit事件中和视图状态将被保留。 如果(的IsPostBack)不要使用,因为控制必须每次在回传被添加,事件!
(德)视图状态的序列化的OnInit后的OnLoad之前发生,所以您的视图状态持久性提供会看到动态添加控件,如果他们在的OnInit增加。
但是在场景你所描述的,大概多视图或简单的隐藏/显示(Visible属性)将是更好的解决方案。
这是因为在OnInit的情况下,当你必须阅读下拉列表和添加新的控件,ViewState是不读(反序列化),但你不知道什么是没用户选择! (你可以做的Request.Form(),但是,感觉有点不对)
这个问题已经搏斗后,而我想出了这些基本规则,这似乎工作,但情况因人而异。
- 使用声明控件尽可能
- 使用数据绑定在可能的情况
- 了解如何工作的ViewState
- 该公开程度属性可以很长的路要走
- 如果你必须使用一个事件处理程序添加控件使用Aydsman的尖端和重建在重写LoadViewState控制。
真正了解的ViewState是必读的。
了解动态控制由示例显示了如何使用数据绑定,而不是动态控件的一些技巧。
真正了解动态控件也澄清了可用于避免动态控件的技术。
希望这有助于与其他同样的问题。
如果确实需要使用动态控制,下面应该工作:
- 在OnInit中,重新创建了页面上的先前请求应验时完全相同的控制层次。 (如果这不是初始请求,当然)
- 的OnInit后,框架会从之前的请求负载的视图状态和所有控件应该在一个稳定的状态了。
- 在onload,即删除不需要的控件和添加必要的。 您还必须以某种方式保存当前控件树在这一点上,在下面的请求在第一步骤中使用。 你可以用它决定了动态控制树是如何创建一个会话变量。 我甚至存储在会话全控件集合一次( 放下你的叉子,这只是一个演示 )。
重新加入,你将不再需要,将在的OnLoad被删除“过时”控制反正似乎有点古怪,但Asp.Net是不是真的设计时考虑到动态控制创建。 如果视图状态加载过程中,不会保留完全相同的控制层次,各种难以发现的缺陷开始潜伏在该网页,因为旧的控制状态被加载到新添加的。
阅读上Asp.Net页面生命周期,特别是在如何的视图状态的作品,它会变得清晰。
编辑:这是关于如何视图状态的行为,什么一个很好的文章在处理动态控件,你应该考虑: http://geekswithblogs.net/FrostRed/archive/2007/02/17/106547.aspx
好。 如果你能摆脱动态地创建控件,那么这样做的 - 否则,我做对子级的,而不是使用Page_Init的Page_Load,但不是把东西如果没有的IsPostBack里面,然后设置,我只是直接的方法。
啊,那是用的ASP.NET Web表单漏抽象的问题。
也许你会有兴趣看一下ASP.NET MVC,这是用于创建本stackoverflow.com网站? 这应该是一个比较容易适合你,从PHP来(因此,脚蹬到了金属,当涉及到HTML和JavaScript)的背景。
我觉得这里的答案是MultiView
控制,使得例如下拉的多视图不同的视图之间切换。
你可能甚至多视图的当前视图属性数据绑定到下拉的价值!
唯一正确的答案被Aydsman给出。 LoadViewState是增加地方重建,并可以以确定哪个控件添加访问视图状态时,他们的视图状态值将恢复动态控件的唯一地方。
我在书中“临ASP.NET 3.5在C#2008”的部分动态控制下创建跨这跑:
如果您需要重新创建一个控制多次,您应该执行在Page.Load事件处理程序中创建控件。 这有让您使用视图状态与动态控制的额外好处。 尽管视图状态的Page.Load事件之前恢复正常,如果创建的处理程序Page.Load性事件的控制,ASP.NET将适用于任何视图状态信息,它具有Page.Load事件处理结束后。 这个过程是自动的。
我没有测试过这一点,但你可能要了解一下吧。