UniqueID和ClientID的來源

作者: Gray Zhang  來源: 博客園  發布時間: 2009-03-06 14:04  閱讀: 2668 次  推薦: 0   原文鏈接   [收藏]  
 
[1] 為什么有UniqueID和ClientID
[2] 回到問題

在《漫話ID》一文中,作者提出了一個問題:為什么在ItemCreated事件中訪問ClientID會導致MyButton無法響應事件,事實上 MyButton無法響應事件是因為他在客戶端的ID被改變了,而此文從UniqueID和ClientID入手,進行較為深入的探討,展示 UniqueID和ClientID是如何生成的,在何時生成,并同時解答《漫話ID》一文中作者的疑問。

為什么有UniqueID和ClientID

這個我想多數使用WebForm的人已經知道了,很大原因上是因為WebForm中存在著數據綁定控件以及自定義控件、View控件之類可以擁有子控件的控件,這就導致在控件樹中很有可能存在著2個ID完全相同的對象,但是由于HTML并不允許ID的重復,于是WebForm發明出了一個叫NamingContainer的東西,并給控件提供了UniqueID和ClientID這兩個屬性,用于區分彼此。

雖然這兩個屬性經常給我們惹來這樣那樣的麻煩,但從總體上來說,這是一個良好的設計,無可厚非。

UniqueID和ClientID如何計算

首先需要明白的一點是,在WebForm中所有的控件最終形成一個樹,每個控件是樹中的一個節點。

在樹型的結構中,每一個節點都擁有0個或1個父節點,而UniqueID和ClientID正是基于“從樹的根部到當前節點的路徑”來計算UniqueID的,我們看一下以下的示例:

<asp:Repeater ID="MyRepeater" runat="server">
    <ItemTemplate>
        <asp:Button ID="MyButton" runat="server" Text="My Button" />ItemTemplate>
asp:Repeater>

我們在MyRepeater中放置了MyButton,而這樣簡單的內容生成出的這個MyButton的最終HTML如下:

請注意看,按鈕的ID變為了MyRepeater_ctl00_MyButton,Name則變為了MyRepeater$ctl00$MyButton,根據《漫話ID》一文中所述,這個ID正好是服務器端控件的ClientID,而Name又正好是服務器端控件的UniqueID。
我們現在要探索的,是為什么ID會變成這個樣子,因此我們先從字面上進行理解,不能看出:

  1. 在這個ID中,有“MyRepeater”字樣,而這正是MyButton的父節點元素Repeater的服務器端ID
  2. 中間有“ctl00”字樣,根據我們編程的習慣,ctl應該表示著control的意思,而00自然就是索引了,這里正好表示“此MyButton是Repeater產生的列表中的第1個元素(下標為0)”
  3. 最后有“MyButton”字樣,正好是MyButton的服務器端ID

好了,將ID分解以后我們就能非常清晰地理解ClientID的生成策略了:

生成ClientID的方法是,在控件本身的ID前加上此控件在數據綁定(如果有)中的索引再加上父控件的ClientID

那么這是怎么做到的呢,這里就提出了NamingContainer的概念,對于NamingContainer,只需要實現一個標記接口INamingContainer。
當控件在計算ClientID時,會查找當前控件的NamingContainer屬性是否為null,如果不是則調用該NamingContainer的一個叫GetUniqueIDPrefix的方法,當然這個方法是遞歸的,在方法體內又會去調用另一個GetUniqueIDPrefix方法。
至于NamingContainer這個屬性是怎么來的,事實上是在調用Controls.Add方法時加上去的,大家可以使用反編譯看一下Control類一個叫AddedControl方法的實現,在此就不作贅述。

[第1頁][第2頁]
0
0
 
標簽:ASP.NET
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()