在 if(!Page.IsPostBack) 中动态创建的控件,应该如何保持其状态?!
问题情况如下:
我在一个页面中添加了一个按钮,并在Page_Load()函数中动态加载了两个控件,方法如下:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Label thelabel = new Label();
thelabel.Text = "哈哈哈";
TextBox theTB = new TextBox();
theTB.Text = "嘿嘿嘿";
form1.Controls.AddAt(0, thelabel);
form1.Controls.AddAt(1, theTB);
}
}
当我点击按钮的时候(按钮没有任何事件处理代码),页面被PostBack
而由于Page_Load()中设置了if (!Page.IsPostBack),所以这两个控件并没有被重新创建
我想问一下,应该如何保持住这两个控件的状态呢?
重新创建一次控件应该不是很好的方法,因为所有控件的数据都要重新绑定,在我这边要动态创建很多这样的控件,并且还要做很多从数据库提取并绑定数据的动作
是否能够在控件第一次被动态创建的时候就使用ViewState或其他方法将他们保持住呢?
请大家指点
谢谢
问题点数:50、回复次数:46Top
1 楼LHA(心动)回复于 2006-08-31 08:21:01 得分 5
一般的情况其实都用不着动态创建控件
怎么会有很多需要动态创建的控件呢?
用用Panel之类的
还有,动态创建的控件 状态应该能自动保存的,
不过好像不是在Page_Load的时候创建,
因为自定义控件 不是也有很多动态创建的控件吗?
大概需要在CreateChildControls里面创建
Top
2 楼lwjvince(Insert into you(memory)values(my all life))回复于 2006-08-31 08:45:52 得分 5
ViewState.Add("X1","0");
if(ViewState["X1"]!=null&&ViewState["X1"].ToString()=="0")Top
3 楼fattycat(最爱胖猫)回复于 2006-08-31 08:52:34 得分 0
楼上这个方法我不太明白
你的X1存储的是控件还是控件的值呢?
页面PostBack后,控件都不见了,存储值有什么用呢?Top
4 楼gezichong(鸽子虫)回复于 2006-08-31 08:57:45 得分 5
保存并读取viewstate:
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
' Sample ArrayList for the page.
Dim PageArrayList As ArrayList
Function CreateArray() As ArrayList
' Create a sample ArrayList.
Dim result As ArrayList
result = New ArrayList(4)
result.Add("item 1")
result.Add("item 2")
result.Add("item 3")
result.Add("item 4")
Return result
End Function
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
If (Me.ViewState("arrayListInViewState") IsNot Nothing) Then
PageArrayList = CType(Me.ViewState("arrayListInViewState"), ArrayList)
Else
' ArrayList isn't in view state, so we need to load it from scratch.
PageArrayList = CreateArray()
End If
' Code that uses PageArrayList.
End Sub
Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
' Save PageArrayList before the page is rendered.
Me.ViewState.Add("arrayListInViewState", PageArrayList)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>View state sample</title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
这个例子看看,,,Top
5 楼gezichong(鸽子虫)回复于 2006-08-31 08:58:25 得分 5
C#:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
// Sample ArrayList for the page.
ArrayList PageArrayList;
ArrayList CreateArray()
{
// Create a sample ArrayList.
ArrayList result = new ArrayList(4);
result.Add("item 1");
result.Add("item 2");
result.Add("item 3");
result.Add("item 4");
return result;
}
void Page_Load(object sender, EventArgs e)
{
if (ViewState["arrayListInViewState"] != null)
{
PageArrayList = (ArrayList)ViewState["arrayListInViewState"];
}
else
{
// ArrayList isn't in view state, so we need to load it from scratch.
PageArrayList = CreateArray();
}
// Code that uses PageArrayList.
}
void Page_PreRender(object sender, EventArgs e)
{
// Save PageArrayList before the page is rendered.
ViewState.Add("arrayListInViewState", PageArrayList);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>View state sample</title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>Top
6 楼lwjvince(Insert into you(memory)values(my all life))回复于 2006-08-31 09:03:49 得分 5
ViewState.Add("X1","0");
if(ViewState["X1"]!=null&&ViewState["X1"].ToString()=="0")
{
//...............//
ViewState["X1"]="1";
}
//X1 只是相当于一个判断状态 不需要定义的.Top
7 楼lwjvince(Insert into you(memory)values(my all life))回复于 2006-08-31 09:05:11 得分 0
if(!IsPostBack)
{
ViewState.Add("X1","0");
//......//
}
Top
8 楼msaspdotnet()回复于 2006-08-31 09:08:13 得分 5
而由于Page_Load()中设置了if (!Page.IsPostBack),所以这两个控件并没有被重新创建
我想问一下,应该如何保持住这两个控件的状态呢?
重新创建一次控件应该不是很好的方法,因为所有控件的数据都要重新绑定,在我这边要动态创建很多这样的控件,并且还要做很多从数据库提取并绑定数据的动作
// if(!Page.IsPostBack)
{
//这里的代码只会在第一次运行时执行,再次提交后不会再运行,
//因此这里创建的控件只会显示在第一次加载页面时,跟本不能保持住控件的状态
//楼主的问题,我想是页面第一次加载时控件绑定数据的问题,而提交之后不用再次绑定
//楼主应该在此创建控件绑定代码(不能在此动态创建控件),以后提交后,控件会自动
//读取ViewState的值,而不会再次去读取数据库,加载数据。
}
Top
9 楼interboy(冯东)回复于 2006-08-31 09:11:49 得分 0
你若是想只让它在第一次载入时执行一次 可以换一个事件 用init事件,它只是在载入时执行回传后它也不执行了!
在private void InitializeComponent()
{
this.Init += new System.EventHandler(this.Page_init);
}
Top
10 楼whslovexyp(菜鸟学习中ing)回复于 2006-08-31 09:14:05 得分 0
创建一个静态的容器,把你要动态创建的控件放容器里就可以了。
private static panel;
page_load()
{
if(!this.ispostback)
{
TextBox tb=new TextBox();
panel.Controls.Add(tb)
}
}Top
11 楼fattycat(最爱胖猫)回复于 2006-08-31 09:29:15 得分 0
TO: msaspdotnet()
我在提交之后也需要绑定控件的值,比如说我点了一个“保存”按钮,页面也会PostBack,但我还需要停留在当前页面继续进行操作,如果控件和控件的值都消失了就不对了
==========================================================
TO: whslovexyp(超级菜鸟)
你这个方法不成啊,在运行的时候报错“未将对象引用设置到对象实例”
Top
12 楼szh3210(/+/=〆)回复于 2006-08-31 09:37:27 得分 0
学习我也想知道回传时如何取动态控件ViewState的值Top
13 楼i169net1(阿康)回复于 2006-08-31 09:51:45 得分 0
Mark...Top
14 楼fattycat(最爱胖猫)回复于 2006-08-31 10:27:14 得分 0
请帮忙Top
15 楼Yellow198267(才高七八斗,学富五六车,改行三四次,月入一两千!)回复于 2006-08-31 10:40:57 得分 0
学习Top
16 楼zjhphc(赵建宏)回复于 2006-08-31 11:01:33 得分 0
我的做法:
控件声明全局变量。
private Label thelabel ;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
thelabel = new Label();
thelabel.Text = "哈哈哈";
form1.Controls.AddAt(0, thelabel); }
}
Top
17 楼fattycat(最爱胖猫)回复于 2006-08-31 11:13:14 得分 0
我的控件都是在Page_Load()当中动态添加的,个数不定啊Top
18 楼zjhphc(赵建宏)回复于 2006-08-31 12:10:26 得分 0
如果最大数确定的话,可以考虑用数组。
不确定但是排列规则的话,用datagridview的模板列吧。Top
19 楼fallingstarNo1(啊龙)回复于 2006-08-31 12:59:36 得分 0
只能重新创建控件!Top
20 楼doitnow2000(大海)回复于 2006-08-31 13:19:04 得分 0
用ViewState保留信息Top
21 楼alicc(狂图)回复于 2006-08-31 13:25:45 得分 0
我认为,你的思路有问题。
你为什么会形成这样的需求,说说你要实现什么功能而要这样做。
.net不支持这个动态创建的viewstate说明不希望用户用这样的方法使用控件。。Top
22 楼fattycat(最爱胖猫)回复于 2006-08-31 14:33:50 得分 0
那我都有哪些方式将信息显示在页面上呢?Top
23 楼fattycat(最爱胖猫)回复于 2006-08-31 14:35:20 得分 0
并且是在指定的位置上Top
24 楼fattycat(最爱胖猫)回复于 2006-08-31 14:40:21 得分 0
而且,无论我用什么样的方式,如果在Page_Load()中不重新绑定的话,被添加上的值还是会消失啊,我还是要重新从数据库中读取,然后绑定啊
大家有什么好方法,可以在页面的某一个位置动态地绑定一个值,并且刷新的时候还能保留其内容呢?Top
25 楼chenyinxin(这里我最菜)回复于 2006-08-31 14:58:51 得分 0
动态创建的控件是不能保存的Top
26 楼sp1234(asp.net不是一个语言,是一个操作系统)回复于 2006-08-31 15:02:06 得分 20
帖子看下来太长了,还是只根据你的问题就事论事吧。
首先必须去掉 IsPostBack 的判断你的程序才能正确执行。
为什么那些asp.net入门书上有很多例子在page_load里边写IsPostBack 判断呢?因为asp.net首先将在页面设计器上写的那些控件装入页面,然后才执行page_load也就是执行那些赋值逾矩。而你的代码是创建控件之后首先赋值,然后才装入页面。
当你把控件装入页面的时候,asp.net会自动将thelabel、theTB的状态(例如你原来设置的字体、背景色、内容等等)以及客户端提交的客户输入的内容给你“回填”到控件上,并且准备好触发应该触发事件(在page_load结束之后就会触发)。因此,你对thelabel、theTB的改变会被asp.net刷新,不写IsPostBack也根本不会出错。反而,如果你写了IsPostBack,asp.net根本无法在页面回发的时候在同样位置找到thelabel、theTB控件了,当然无法回填任何数据。
那么那些入门书上的那种代码,是在asp.net对控件处理完(添加入页面)之后,因此你写的代码会刷新asp.net回填的值,因此需要IsPostBack来决定到底维持哪一个值。
而对于DataGrid(GridView)等,由于它在状态中根本不保持数据内容(TextBox会自动保持text属性,但是表格并不自动保持内容数据,这是有差别的),所以比必须重新绑定数据,这也是一种不能使用IsPostBack的情况。
最后,要想在说清楚一些,我把你的代码用asp.net处理设计器上控件的那种固有的那种逻辑改一下(我没有测试是否正确,你理解意思就好):
rotected void Page_Load(object sender, EventArgs e)
{
Label thelabel = new Label();
TextBox theTB = new TextBox();
form1.Controls.AddAt(0, thelabel);
form1.Controls.AddAt(1, theTB);
if (!Page.IsPostBack)
{
thelabel.Text = "哈哈哈";
theTB.Text = "嘿嘿嘿";
}
}
Top
27 楼sp1234(asp.net不是一个语言,是一个操作系统)回复于 2006-08-31 15:16:33 得分 0
顺便说一下,看上去这个问题解决了。但是实际上这并没有透彻解决asp.net软件设计问题。
好的、可以长期利用的软件是组件化的,而不是按照页面来设计的。通常对一些数据源(例如一个SQL语句或者一个数据库记录的主键值)输入参数设计一些应用控件,例如根据“栏目”的id号自动产生本栏目的导航列表,并且根据一个“风格”参数生成横向、纵向、平铺、树形等多种形式,这种应用控件才是软件ui设计的真正核心技术,是你公司产品背后的真正英雄。当你需要写一个页面的时候,把业务控件拿过来根据用户的喜好随意摆放、设置一下简单的几个参数,一个应用程序应该在十几分钟之内产生出来。
这时候,控件装入数据的时机根本不能考虑放到page_load中去。而是要根据控件的机制去设计。
我现在如果正规地去写个商业程序,已经几乎根本不在页面上放任何东西,整个页面中仅仅放一个控件。我已经习惯使用控件来看软件开发问题。我也不会允许程序员从页面角度去写涉及需求和应用领域数据的内容,而是要求程序员在其它project里写好应用程序控件——至少是一个用户控件,然后我拿过来“随心所欲”地组合进简单的页面里。所以楼主的问题我其实并不会遇到。Top
28 楼myfattycat(最爱胖猫~的马甲 ^o^)回复于 2006-08-31 15:42:48 得分 0
谢谢sp1234高手,总是从经验和原理的角度来进行讲解,这让我们这些新人受益匪浅
但是这段代码还有一个问题
在我将控件声明和添加的过程放在if(@Page.IsPostBack)外边之后,TextBox的控件和值都保留下来了,而Label的值却没有保存下来
我看了一下输出后的HTML,有<span></span>标记,说明Label控件在PostBack后又被创建了,但由于赋值工作在if(@Page.IsPostBack)内部进行,所以没有进行赋值
但是TextBox的值怎么可以被保留,而Label却不能呢?
Top
29 楼Jinpanxu(浪)回复于 2006-08-31 15:58:26 得分 0
onload事件在每次刷新时都执行,所以在你提交后,页面又重新生成了Label,所以就出现了你那种效果.
rotected void Page_Load(object sender, EventArgs e)
{
Label thelabel = new Label();
TextBox theTB = new TextBox();
form1.Controls.AddAt(0, thelabel);
form1.Controls.AddAt(1, theTB);
thelabel.Text = "哈哈哈";
theTB.Text = "嘿嘿嘿";
}
这就达到你想要的效果了
Top
30 楼fattycat(最爱胖猫)回复于 2006-08-31 16:00:02 得分 0
呵呵呵~楼上确实是我想要的效果,但也是我最想避免的实现形式Top
31 楼xingdongfang(xingdongfang)回复于 2006-08-31 16:12:53 得分 0
动态加载控件,并且要维护控件的视图。
仅需要做如下一件事情。
在ONPREINIT里面去执行加载,而不管是不是POSTBACK
就可以了。
我做过。Top
32 楼liwei818()回复于 2006-08-31 16:34:53 得分 0
upTop
33 楼fattycat(最爱胖猫)回复于 2006-08-31 19:48:30 得分 0
upupTop
34 楼sp1234(asp.net不是一个语言,是一个操作系统)回复于 2006-09-01 21:41:53 得分 0
我没有仔细看你的代码,我试了一下:
this.PlaceHolder1.Controls.Add(new Label());
if (!this.IsPostBack)
((Label)this.PlaceHolder1.Controls[0]).Text = "haha";
然后让页面上有提交按钮,并没有丢失这个Text的值。你还是在后台那个“if(”语句设个断点,看看Label的EnableViewState、Text的值有什么异常。
我要说明一下,绝对不能放在 onInit 相关的阶段去创建动态控件。因为之所以使用动态空间,往往就是为了根据页面上的实际ViewState(这些专门记录状态的机制)来选择插入的控件的。而Init阶段还没有回填ViewState。那些在页面设计器上控件之所以可以自动产生在init阶段创建,是因为他们本身就是傻瓜的,不是动态的。Top
35 楼Mijie_John()回复于 2006-09-01 22:12:27 得分 0
帮你顶Top
36 楼supNate(铅笔)回复于 2006-09-03 20:57:36 得分 0
你的问题我可以回答:
动态添加控件肯定是每次都要添加的,而不是仅在postback里。正确的做法是创建后立即将其加入到页面层次结构中,somecontrol.Controls.Add(xxx),然后再设置其属性。否则视图状态无法恢复。
所以顺序应该是:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Label thelabel = new Label();
TextBox theTB = new TextBox();
form1.Controls.AddAt(0, thelabel);
form1.Controls.AddAt(1, theTB);
thelabel.Text = "哈哈哈";
theTB.Text = "嘿嘿嘿";
}
}
另外在aspx中直接声明的控件并不是只创建一次,而是每次都自动创建,以声明的方式而已。
Top
37 楼wangjs211()回复于 2006-09-03 22:09:31 得分 0
sp1234(行动力用户、移动、协同、免费软件)
高手Top
38 楼flyinging(一路走来)回复于 2006-09-03 22:09:49 得分 0
动态创建的在回发之后就没有了,不能自动保存状态,
1,手动保存之后,重新绑定,封装到Viewstate里
2,不要动态创建了Top
39 楼szh3210(/+/=〆)回复于 2006-09-04 12:23:20 得分 0
取 Request.Params的值Top
40 楼fattycat(最爱胖猫)回复于 2006-09-05 06:58:42 得分 0
还是不成
忽然想到,用Ajax是否可以实现??!!Top
41 楼exiori(IORI)回复于 2006-09-05 07:38:59 得分 0
可以使用AJAX实现。Top
42 楼pkkfaii(火柴头)回复于 2006-09-05 07:59:41 得分 0
学习中。。Top
43 楼qiangv(专业顶贴,只问不答)回复于 2006-09-05 08:33:44 得分 0
markTop
44 楼fattycat(最爱胖猫)回复于 2006-09-05 09:07:55 得分 0
好像Atlas不能应用于动态创建的控件?~
-_-||Top
45 楼fattycat(最爱胖猫)回复于 2006-09-05 09:10:52 得分 0
哦~是可以的~已经可以了~~Bill gates灵魂附体~~~
呵呵 ^o^Top
46 楼fattycat(最爱胖猫)回复于 2006-09-05 09:38:21 得分 0
但应用Atlas之后,似乎无法FindControl() ??!!Top




