天天看點

INamingContainer接口解決多個自定義控件ID沖突

CreateChildControls方法一般用于建立組合控件,在此方法中可以建立多個自己需要的控件,進行執行個體化,指派等等.

我們建立個複合控件,如下:

public class CompositeCtl: WebControl

    {

        protected override void CreateChildControls()

        {

            TextBox textbox = new TextBox();

            textbox.ID = "txt";

            this.Controls.Add(textbox);

            Button button = new Button();

            button.ID = "btnOk";

            button.Text = "Ok";

            this.Controls.Add(button);

        }

    }

在用戶端,我們引用2遍我們的這個自定義控件:

<myCtl:INamingConatinerControl ID="namingCtl1" runat="server" />

        <br />

        <myCtl:INamingConatinerControl ID="namingCtl2" runat="server" />

生成的HTML代碼如下:

<span id="namingCtl1"><input name="txt" type="text" id="txt" /><input type="submit" name="btnOk" value="Ok" id="btnOk" /></span>

        <span id="namingCtl2"><input name="txt" type="text" id="txt" /><input type="submit" name="btnOk" value="Ok" id="btnOk" /></span>

上面我們可以看到比較嚴重的問題是:

2個文本框和按鈕的用戶端id居然是一樣的,這樣我們無法利用用戶端的JS語句getElementById來得到某個具體的

文本框或者按鈕.

解決辦法:

讓自定義控件實作INamingContainer(命名容器)接口,其他什麼都不用做,代碼會自動為以控件的ID作為字首進行拼接.

控件正式代碼如下:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Linq;

using System.Text;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace BlogControl.Basic

{

    public class INamingConatinerControl : WebControl,INamingContainer

}

這樣生成的HTML代碼如下:

<span id="namingCtl1"><input name="namingCtl1$txt" type="text" id="namingCtl1_txt" /><input type="submit" name="namingCtl1$btnOk" value="Ok" id="namingCtl1_btnOk" /></span>

        <span id="namingCtl2"><input name="namingCtl2$txt" type="text" id="namingCtl2_txt" /><input type="submit" name="namingCtl2$btnOk" value="Ok" id="namingCtl2_btnOk" /></span>

我們可以看到:

伺服器端的name: 控件名 + $ + ID

用戶端ID:           控件名 + _  + ID

差別在于連接配接的符号不同.

這裡我們提一下控件的3種ID:

1) ID - 就是我們給它命名的 ID

2) UniqueID - 控件的伺服器端ID (生成HTML後的name)

3) ClientID   - 控件的用戶端ID  (生成HTML後的id)

最後我們要提一下的是:

如果控件繼承了 CompositeControl,就不需要再實作INamingContainer接口了,因為

CompositeControl本身就實作了該接口.

繼續閱讀