前言
MSDN問題連結:請問使用 ajax dynamic add control時,為何在masterpage會沒有反應呢
雖然我實在很討厭『動態新增控制項』,但實在太多人問類似的問題了,只好寫個Sample,這樣以後貼個連結就搞定了。
需求
套用MasterPage,使用UpdatePanel,每按一次按鈕,畫面上要多一個TextBox,且原本輸入的值要留著。
說明
MSDN問題連結:請問使用 ajax dynamic add control時,為何在masterpage會沒有反應呢
雖然我實在很討厭『動態新增控制項』,但實在太多人問類似的問題了,只好寫個Sample,這樣以後貼個連結就搞定了。
需求
套用MasterPage,使用UpdatePanel,每按一次按鈕,畫面上要多一個TextBox,且原本輸入的值要留著。
說明
- Server control的Button,預設Render成HTML是submit。這邊動態新增控制項,得確定postback是由這個button所發動,所以需要將button的UseSubmitBehavior屬性設定為false。這樣子可以讓Button在Render的時候,Render成button的tag,且在onclick的時候會呼叫__doPostBack的js function。
- 在Page_Load的時候,透過this.Request.Form["__EVENTTARGET"]來判斷postback的發動者,是否為用來動態新增控制項的Button。這邊因為套用了MasterPage,所以判斷要用Button的UniqueID屬性來判斷。
- 透過一個ViewState來暫存,這一次到底要多新增幾個TextBox,且封裝成property,讓用的人更輕鬆。
範例
.aspx
01 | < asp:Content ID = "Content1" ContentPlaceHolderID = "HeadContent" runat = "Server" > |
02 | </ asp:Content > |
03 | < asp:Content ID = "Content2" ContentPlaceHolderID = "MainContent" runat = "Server" > |
04 | < asp:ScriptManager ID = "ScriptManager1" runat = "server" > |
05 | </ asp:ScriptManager > |
06 | < asp:UpdatePanel ID = "UpdatePanel1" runat = "server" UpdateMode = "Conditional" > |
07 | < ContentTemplate > |
08 | < asp:Button ID = "Button1" runat = "server" Text = "再多一個textbox" UseSubmitBehavior = "false" /> |
09 | < br /> |
10 | dynamic adding controls:< br /> |
11 | < asp:PlaceHolder ID = "PlaceHolder1" runat = "server" ></ asp:PlaceHolder > |
12 | </ ContentTemplate > |
13 | </ asp:UpdatePanel > |
14 | </ asp:Content > |
.aspx.cs
01 | public partial class Sample : System.Web.UI.Page |
02 | { |
03 | private static readonly int defaultControlCount = 5; |
04 | |
05 | private int MoreTextBoxCount |
06 | { |
07 | get |
08 | { |
09 | return this .ViewState[ "MoreTextBoxCount" ] == null ? 0 : Convert.ToInt32( this .ViewState[ "MoreTextBoxCount" ]); |
10 | } |
11 | set |
12 | { |
13 | this .ViewState[ "MoreTextBoxCount" ] = value; |
14 | } |
15 | } |
16 | |
17 | protected void Page_Load( object sender, EventArgs e) |
18 | { |
19 | if ( this .Request.Form[ "__EVENTTARGET" ] == this .Button1.UniqueID) |
20 | { |
21 | this .MoreTextBoxCount += 1; |
22 | } |
23 | |
24 | this .GenerateTextBox(); |
25 | } |
26 | |
27 | private void GenerateTextBox() |
28 | { |
29 | var count = defaultControlCount + this .MoreTextBoxCount; |
30 | for ( int i = 0; i < count; i++) |
31 | { |
32 | var textbox = new TextBox(); |
33 | textbox.ID = string .Format( "joey_txt{0}" , i.ToString()); |
34 | var label = new Label(); |
35 | label.ID = string .Format( "joey_lbl{0}" , i.ToString()); |
36 | label.Text = "<br/>" ; |
37 | this .PlaceHolder1.Controls.Add(textbox); |
38 | this .PlaceHolder1.Controls.Add(label); |
39 | } |
40 | } |
41 | } |
結果畫面
結論
可以的話,應盡量避免動態新增控制項,因為要控制連動是一件麻煩的事,控制項太多也會導致ViewState過大。可以用簡單的方法,就不要自刁耍帥,當需求異動的時候,會花很多功夫為了維持動態新增控制項的穩定。另外,動態新增控制項時,請記得新增的控制項ID屬性要給值,不然可能會出現莫名的問題。
動態新增控制項,反而比較靈活運用的地方是在新增user control,因為各自控制自己的邏輯且互不相干。
還有,跟本篇無關,但我要強調一下:UpdatePanel != Ajax。
Source Code: DynamicAddControls.zip
可以的話,應盡量避免動態新增控制項,因為要控制連動是一件麻煩的事,控制項太多也會導致ViewState過大。可以用簡單的方法,就不要自刁耍帥,當需求異動的時候,會花很多功夫為了維持動態新增控制項的穩定。另外,動態新增控制項時,請記得新增的控制項ID屬性要給值,不然可能會出現莫名的問題。
動態新增控制項,反而比較靈活運用的地方是在新增user control,因為各自控制自己的邏輯且互不相干。
還有,跟本篇無關,但我要強調一下:UpdatePanel != Ajax。
Source Code: DynamicAddControls.zip
沒有留言:
張貼留言