自問對如何把玩Dynamic Web Control,Page Life Cycle是怎樣,如何重構Controls和ViewState都很了解。
但奈何今天敗在一個CheckBox Control下,花了我半天才搞定,所以在Blog上做一個記錄和分享。
而遇到的問題就是,
在同一個Form內,PostBack後,所有動態Control都存取都正常,唯獨是任何CheckBox Controls的Checked屬性一直都是False。
搞了一段時間後,我決定由最原始的方式 Request.Form 的方式,去找出問題在那裡。
或者這樣說太抽象,先看看Source Code和Screen Shot。
Markup 方面很簡單,一個Button,一個PlaceHolder。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="test.aspx.cs" Inherits="test" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title></title> </head> <body style="font-family: Tahoma; font-size: 11px;"> <form id="form1" runat="server"> <div> <asp:Button ID="btnAdd" runat="server" Text="Add CheckBox" OnClick="btnAdd_Click" /> <asp:PlaceHolder ID="PlaceHolder1" runat="server" /> </div> </form> </body> </html>再來是Source部份,留意Line:62 & 63 :
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class test : System.Web.UI.Page { protected int NumberOfControls { get { return (int)ViewState["ControlCount"]; } set { ViewState["ControlCount"] = value; } } protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) NumberOfControls = 0; else RecreateControls(); } protected void btnAdd_Click(object sender, EventArgs e) { CreateControls(this.NumberOfControls); this.NumberOfControls++; } private void CreateControls(int i) { CheckBox chk = new CheckBox(); chk.ID = "chk" + i.ToString(); Label lbl = new Label { ID = "lbl" + i.ToString(), Text = " Index : " + i.ToString() }; PlaceHolder1.Controls.Add(lbl); PlaceHolder1.Controls.Add(chk); PlaceHolder1.Controls.Add(new Literal { Text = " " }); } private void RecreateControls() { int count = this.NumberOfControls; for (int i = 0; i < count; i++) CreateControls(i); int idx = 0; for (int x = 0; x < PlaceHolder1.Controls.Count; x++) { Control ctl = PlaceHolder1.Controls[x]; if (ctl is Label) { Response.Write(((Label)ctl).Text); } else if (ctl is CheckBox) { Response.Write(" Checked : " + ((CheckBox)ctl).Checked.ToString() + " | " + Request.Form["chk" + idx.ToString()] + " "); idx++; } } } }
得出來的結果如下圖 :
使用((CheckBox)ctl).Checked.ToString()輸出是False,但Request.Form找取Value卻是"on",最奇怪就是用IE的Deveper Tool看一看文件,明明真的有CHECKED="checked",換句話說,ASP.NET的CheckBox Control在勾選或取消勾選雖然會變更Client-Side Value和Checked屬性,但不會更改Control States的Checked的屬性,這就是問題的根源,於是我立即想起沒有PostBack的原故。
那如何解決呢? 很簡單,就是把CheckBox的AutoPostBack設成True,再在CheckedChanged的Event加上Event Handler就可以了。
整理後的Source :
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class test : System.Web.UI.Page { protected int NumberOfControls { get { return (int)ViewState["ControlCount"]; } set { ViewState["ControlCount"] = value; } } protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) NumberOfControls = 0; else RecreateControls(); } protected void btnAdd_Click(object sender, EventArgs e) { CreateControls(this.NumberOfControls); this.NumberOfControls++; } private void CreateControls(int i) { CheckBox chk = new CheckBox(); chk.ID = "chk" + i.ToString(); chk.AutoPostBack = true; chk.CheckedChanged += CheckedChanged; Label lbl = new Label { ID = "lbl" + i.ToString(), Text = " Index : " + i.ToString() }; PlaceHolder1.Controls.Add(lbl); PlaceHolder1.Controls.Add(chk); PlaceHolder1.Controls.Add(new Literal { Text = " " }); } private void CheckedChanged(Object sender, EventArgs e) { } private void RecreateControls() { int count = this.NumberOfControls; for (int i = 0; i < count; i++) CreateControls(i); int idx = 0; for (int x = 0; x < PlaceHolder1.Controls.Count; x++) { Control ctl = PlaceHolder1.Controls[x]; if (ctl is Label) { Response.Write(((Label)ctl).Text); } else if (ctl is CheckBox) { Response.Write(" Checked : " + ((CheckBox)ctl).Checked.ToString() + " | " + Request.Form["chk" + idx.ToString()] + " "); idx++; } } } }
沒有留言:
發佈留言