问题提出:
在web页面动态增加服务器端控件,并通过动态增加的控件实现事件的交互。
实验探索:
为了实验方便,在这里我选用了最简单的Button控件。
在页面上定义两个Button(增加,测试)和一个label(用来显示交互信息)控件
protected System.Web.UI.WebControls.Button btn_Test;
protected System.Web.UI.WebControls.Button btn_Add;
protected System.Web.UI.WebControls.Label l_ShowMsg;
要在增加按钮按下的时候动态增加Button控件,我写了下面的方法
private void btn_Add_Click(object sender, System.EventArgs e)
{
Button btnAdd = new Button(); //定义要增加的按钮控件
btnAdd.Text = "新增按钮";
btnAdd.ID = "btnAdd"; //按钮的ID
this.FindControl("form1").Controls.Add(btnAdd);//往表单里增加此按钮,不知道这句有其他写法没有
}
这时候我们运行,结果如下:
(图一)
在运行时发现,点击了增加按钮以后,在页面上增加一个按钮
(图二)
但是当我们再次点击增加,并没有像我们想像中那样再增加一个按钮,而是依然是图二的样子(就算增加成功了也应该有个问题,有的朋友应该已经看出来了,就是控件的ID是相同的,就算增加成功了,运行的时候也会提示ID不唯一的错误,就是上面代码我加粗显示的地方)。而且当我们点击测试按钮时, 当页面回传,屏幕会恢复到图一的样子,也就是说我们刚才动态增加的按钮不见了。这种结果肯定不是我们想要的,我们想要的是增加了这个动态控件后,它可以像在页面设计阶段时增加的服务器控件一样使用。这就引出的问题一:“如何保存动态增加控件的页面状态?”
这个问题到现在我也没有得到良好的解决,但是经过实验,我用一种比较笨拙的方法来实现。
我们修改代码。
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button btn_Test;
protected System.Web.UI.WebControls.Button btn_Add;
protected System.Web.UI.WebControls.Label l_ShowMsg;
protected static ArrayList arr = new ArrayList();
…….
…….
}
在文件的开始定义时我们定义了一个静态的ArrayList。这个ArrayList的作用是储存我们增加的按钮对象。之于用静态的是为了让它在回传时依然会保存上一次的状态值。(不知道有什么好的办法没有?对这点我一直存有疑问。)
private void btn_Add_Click(object sender, System.EventArgs e)
{
Button btnAdd = new Button(); //定义要增加的按钮控件
btnAdd.Text = "新增按钮"+ arr.Count.ToString();
btnAdd.ID = "btnAdd"+ arr.Count.ToString(); //按钮的ID
arr.Add(btnAdd);
this.FindControl("form1").Controls.Add(btnAdd);
}
在上面,我们把增加的Button的名称和ID都和ArrayList的数量关联起来,就不会出现上面所说的ID名称重复的情况。这样修改后我们再运行。结果是
第一次点击增加以后,屏幕上会增加一个按钮“新增按钮0”,再点后,按钮的名称会变为“新增按钮1”。。。。。并以此类推,无论我们点几次,屏幕上始终只有一个按钮,而按钮的名字就是我们点的次数-1。同样,点击“测试”按钮,出现的结果和上例的一样,我们动态增加的按钮依旧会消失。另外有一个重大问题。因为我们使用的是静态ArrayList,所以当我们关闭了页面以后,再马上打开,点击增加,这时候按钮的值并不是从0开始,而是从你上次关闭时候的值+1,郁闷中。。。。。。。
这就引出了今天的第二个问题:“有什么办法可以替换掉这个静态变量,或者有什么办法能在页面关闭后清空它?”
静态变量的事情我们暂时先不管。我们先实现增加多个和刷新的时候不减少。
我们知道,因为我们使用了这个静态的ArrayList,所以我们每次点击增加时所增加的Button其实都已经储存在ArrayList里面了,只是在页面Onload时,页面里的控件状态恢复到页面设计时的样子,然后再通过btn_Add_Click()方法增加了一个。所以我们在Page_Load()时,让页面再次加载ArrayList里的button object就可以了。因此,我们修改Page_Load()方法
private void Page_Load(object sender, System.EventArgs e)
{
for(int i=0;i<arr.Count;i++)
{
this.FindControl("form1").Controls.Add((Button)arr[i]);
}
}
再次运行我们发现,我们得到了我们想要的结果,点击一次增加一个Button控件,并且按“测试”的时候也不会消失。(其实不是没有消失,而是我们重新加载了一遍,呵呵)
(图三)
以上就是增加了多个服务器端控件的实现方法。办法有够笨拙的,所以希望大家有好的办法一定要不吝赐教。
我们继续。控件是增加上了,但是如何交互呢?为此,我手动的在增加按钮的时候加了一个事件(加粗部分)
private void btn_Add_Click(object sender, System.EventArgs e)
{
Button btnAdd = new Button(); //定义要增加的按钮控件
btnAdd.Text = "新增按钮"+ arr.Count.ToString();
btnAdd.ID = "btnAdd"+ arr.Count.ToString(); //按钮的ID
btnAdd.Click += new System.EventHandler(this.btn1_Click);
arr.Add(btnAdd);
this.FindControl("form1").Controls.Add(btnAdd);
}
同时增加这个btn1_Click事件方法
private void btn1_Click(object sender, System.EventArgs e)
{
Button bt = (Button) sender;
l_ShowMsg.Text = bt.Text; //改变那个提示Label的显示文字
}
经过测试,我发现当我们按下了新增加的按钮的时候btn1_Click()的事件被触发了,l_ShowMsg.Text也被赋予了按钮的显示名称,但是在页面上却无论如何也不发生改变。依然和图三一样。但是我们却可以通过事件访问动态增加的控件的属性和值。难道是自增加控件不能访问在设计阶段增加的控件?如果可以的话如何访问?这就是我今天的第三个问题。
问题结论:
我们实现了动态增加服务器端控件,却实现的并不漂亮,而且有很多隐藏的问题。这些问题导致了这个方法并不实用。我希望大家能多多指教,让我能把上面的方法完善起来。谢谢!
其他:
这段代码仅仅为测试用的,所以不具有任何的通用性,希望大家不要在这方面指责我,我只是为了测试是否能实现,呵呵。