2013年9月4日 星期三

[轉貼] 套用MasterPage後,如何動態新增控制項

出處:http://www.dotblogs.com.tw/hatelove/archive/2011/11/30/how-to-dynamically-add-controls-in-masterpage.aspx

前言
MSDN問題連結:
請問使用 ajax dynamic add control時,為何在masterpage會沒有反應呢

雖然我實在很討厭『動態新增控制項』,但實在太多人問類似的問題了,只好寫個Sample,這樣以後貼個連結就搞定了。
需求 
套用MasterPage,使用UpdatePanel,每按一次按鈕,畫面上要多一個TextBox,且原本輸入的值要留著。

說明
  1. Server control的Button,預設Render成HTML是submit。這邊動態新增控制項,得確定postback是由這個button所發動,所以需要將button的UseSubmitBehavior屬性設定為false。這樣子可以讓Button在Render的時候,Render成button的tag,且在onclick的時候會呼叫__doPostBack的js function。
  2. 在Page_Load的時候,透過this.Request.Form["__EVENTTARGET"]來判斷postback的發動者,是否為用來動態新增控制項的Button。這邊因為套用了MasterPage,所以判斷要用Button的UniqueID屬性來判斷。
  3. 透過一個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
01public 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}

結果畫面
一開始:
image

輸入值之後,按了一次按鈕:
image

修改值後,按了第二次按鈕:
image

結論
可以的話,應盡量避免動態新增控制項,因為要控制連動是一件麻煩的事,控制項太多也會導致ViewState過大。可以用簡單的方法,就不要自刁耍帥,當需求異動的時候,會花很多功夫為了維持動態新增控制項的穩定。另外,動態新增控制項時,請記得新增的控制項ID屬性要給值,不然可能會出現莫名的問題。

動態新增控制項,反而比較靈活運用的地方是在新增user control,因為各自控制自己的邏輯且互不相干。

還有,跟本篇無關,但我要強調一下:UpdatePanel != Ajax。

Source CodeDynamicAddControls.zip

沒有留言:

張貼留言