先前曾提出在MasterPage中解決ClientID被加料的方法,最近發現原來的做法有些小缺點。

原先的邏輯只額外多搜尋ContentPlaceHolder的字頭(Prefix),但是若其中有UserControl,則UserControl的ClientID還會被加上UserControl的ID。例如: (UC11中只有一個TextBox1)

<asp:Content ID="Content2" ContentPlaceHolderID="Editor" Runat="Server">
    <uc1:UC1 ID="UC11" runat="server" />
</asp:Content>

實際的TextBox1的ClientID會變成ctl00_Editor_UC11_TextBox1,原先的做法只會Search到ctl00_Editor_TextBox1,因此UserControl下的物件就變成化外之民。

<input name="ctl00$Editor$UC11$TextBox1" type="text" id="ctl00_Editor_UC11_TextBox1" />

我修改了原有的程式,將UserControl的ClientID也加入要搜索的字頭之一,同時對ContentPlaceHolder下的Control也要逐一巡迴檢查,這樣就能把UserControl下的物件納入afa_mpget的查找範圍內。

    public static void searchContentPlaceHolder(Control ctrl, List<string> lst)
    {
        if (ctrl is ContentPlaceHolder || ctrl is UserControl)
            lst.Add(ctrl.ClientID);
        if (ctrl.HasControls())
        {
            foreach (Control c in ctrl.Controls)
                searchContentPlaceHolder(c, lst);
        }
    }

只是,原先與網友大估討論過將邏輯放在Page_Init解決對ViewState干擾的做法,由於在搜尋的時候必須確認網頁上的Control物件都已Create妥當,以免在列舉時有遺珠,因此放在Page_Load()比較OK。最終決定的做法: 放在Page_Load()+Page.Header.Controls.Add(...)。


Comments

# by 大估

感謝黑暗大大~ 又學到東西了~

# by sam

問下黑大~ 我現在開發一個自訂控制項(server端) 當中有jQuery的callback來當作client的回呼事件 這個控制項在獨立的網頁上使用是正常無誤的~ 但在Masterpage當中使用時,後端的callback機制卻無法 產生事件來~ 能否麻煩黑大針對這個問題幫我想想法子先...

# by Jeffrey

to sam, "當中有jQuery的callback來當作client的回呼事件... 後端的callback機制卻無法產生事件來... ",看不是很懂,看要不要把關鍵部分的Code貼出來,大家再幫忙研究。

# by sam

Me.Page.ClientScript.GetCallbackEventReference(Me, "'" & Item.Key & "'", Item.ClientCallBack, "''") & ";" 上面這段是我在自訂控制項裡所寫的callback產生語法 當然我也先實作了這個控制項的 ICallbackEventHandler ME <---就是我的自訂控制項本身來源 下方是產生後的Jquery script <script type="text/javascript"> //<![CDATA[ WebForm_InitCallback();$(document).ready(function() { $('#ctl00_ContentPlaceHolder1_Label1').contextMenu('ctl00_ContentPlaceHolder1_TM',{ bindings: { 'Excel': function(t) { WebForm_DoCallback('ctl00_ContentPlaceHolder1_TM','Excel',ReceiveServerData,'',null,false); } } }); }); //]]> </script> 在一般單一的Aspx網頁之中可以正常的run 但加諸在masterpage就沒有辦法針對自訂控制項來進行 相關的click事件 搞不太懂,是不是因為包在masterpage當中的原因... 試了很多種方法,它還是沒有辦法將click事件傳回到server... 煩人的masterpage~~~

# by Jeffrey

to sam, 由你描述的情境,我懷疑是因為套用Materpage後ClientId不同造成的,建議你檢視套用MasterPage時的HTML原始碼,看看ctl00_ContentPlaceHolder1_Label1、ctl00_ContentPlaceHolder1_TM這些ID是否已改變了。

# by sam

to Jeffrey 我也想過這問題,是不是因為控制項在其底層所造成~ 但事實或許不然哦... 因為雖然被改變其ID但,我可以在後端自由改變其ID 覺得是出在開發的控制項當中~不知怎配合Masterpage 來套用配合,因為我不單單是在單一網頁配合Masterpage 是還有一層的自訂控制項元件在網頁當中使用... 有點就 Masterpage--->aspx--->自訂控制項 單一網頁的問題我會處理,但裡頭加了自訂控制項後,事件就 無法觸發...-,- 快瘋囉=.=

# by sam

有沒有大大在開發自訂控制項時,有遇過類似的問題呢? 簡單來說 1.在單一的表單裡引用自訂控制項,所有的callback事件都得以正常觸發與使用 2,在masterpage的模式套用底下,jquery的語法可以正常觸發,但server端的事件卻無法觸發呢? 我真的想破頭了... 也隨意配合masterpage產生html時的加料名(動態在自訂控制項裡將Render方法裡修正ID),但這是javascrip的影響而已,並不是隨著後端的事件而影響,這實在是很麻煩,搞不懂為何在Masterpage的套用底下,自訂控制項的事件無法得以觸發呢....=.="' 倘若有大大有這方面的開發經驗,再分享出來...萬分感謝...

# by Jeffrey

to sam, 我覺得"動態在自訂控制項裡將Render方法裡修正ID"跟"server端的事件卻無法觸發"有關,UserControl裡的ClientID加料為的是要跟Server端相呼應,在Render更動ClientID,可能會導致Server端的機制失效。

# by sam

to : Jeffrey 動態異動僅為了測試masterpage的原故 實際上我是用這個控制項本身的id為條件(me.clientid) 在Render方法裡是為了配合輸出jquery的html 如下: WebForm_InitCallback();$(document).ready(function() { $('#ctl00_ContentPlaceHolder1_Label1').contextMenu('ctl00_ContentPlaceHolder1_TM',{ bindings: { 'Excel': function(t) { WebForm_DoCallback('ctl00_ContentPlaceHolder1_TM','Excel',ReceiveServerData,'',null,false); ctl00_ContentPlaceHolder1_TM <---就是本身控制項的id 但如果在單一網頁之中就變成 WebForm_InitCallback();$(document).ready(function() { $('#Label1').contextMenu('TM',{ bindings: { 'Excel': function(t) { WebForm_DoCallback('TM','Excel',ReceiveServerData,'',null,false); TM<------單一網頁的名稱 就很正常的RUN...

# by Jeffrey

to sam, 原來我誤解你的意思,你變更的是呼叫時配合MasterPage使用加料版的ClientId,而不是去控制ClientId。這樣子看起來,程式應該會正常運作才對,我沒什麼點子。如果可行,看要不要把會出錯的網頁提取成可執行的小Web Application,讓大家幫你深入研究看看。

# by Sam

to Jeffrey 大大~~~ http://www.dotblogs.com.tw/jeff377/archive/2008/11/06/5876.aspx 以上的網址是我寫自訂控制項的靈感來源 這個網站將jquery寫成幾則很不錯的自訂控制項 當中的右鍵選單也就是我提出的問題來源集 放置一般單一網頁可以正常的Run 但老話重提,一旦以Masterpage的模式就躺了.... 目前公司著重這方面的方案,倘若可行...勢必可以增加 小弟的產能...........但卡關卡粉久了~~~ 若可以,希望j大能一起實作且試著看看這問題先~

# by Jeffrey

to sam, 試了一下,我想你的問題出在 'Excel': function(t) { WebForm_DoCallback(... 這裡的'Excel'應該也要對應到己加料的ClientId才對。我試改了TBContextMenu.vb Render(), 先算出加料的前置語法: Dim sPrefix As String sPrefix = Me.ClientID.Substring(0, Me.ClientID.Length - Me.ID.Length) 在產生bindings對應時加上: oScript.AppendLine("'" & sPrefix & oItem.Key & "': function(t) {") 試了一下,這樣子在MasterPage下就可以動了。

# by sam

TO Jeffery : j 大大...您真是一語驚醒夢中人!! 我只顧著會異動的元件名稱,沒想到那個被點選的物件也會 隨著變化clientID.... 好在佳有您幫我看穿這問題...這問題困擾我很久了!! 再次強力的感謝您的指導! 謝謝...謝謝! ^.^

Post a comment