概述C#復(fù)合控件構(gòu)建
C#復(fù)合控件構(gòu)建
這個(gè)ListMover控件包含兩個(gè)EnhancedListBox控件,還有一些按鈕用于在兩個(gè)列表之間來回移動(dòng)項(xiàng)。借助于這些C#復(fù)合控件構(gòu)建技術(shù),你可以學(xué)習(xí)如何創(chuàng)建子控。對(duì)于這個(gè)控件,你要注意的是某些事情必須發(fā)生的位置。
首先,借助于與在以前的控件中相同的技術(shù),你必須把在這個(gè)控件中需要的JavaScript代碼添加到OnInit事件的重載版本中。如你在上一個(gè)控件中所做的一樣,你也是使用JavaScript存取一個(gè)ListBox中的元素。而且,我已經(jīng)編制了函數(shù)分別實(shí)現(xiàn)把項(xiàng)添加到一個(gè)列表,從一個(gè)列表中刪除項(xiàng),以及從一個(gè)列表中添加或刪除所有項(xiàng)。
我已經(jīng)進(jìn)行了功能的分離,而不是創(chuàng)建單個(gè)“move”方法;這樣以來,我可以實(shí)現(xiàn)基于屬性設(shè)置而使得從一個(gè)列表中刪除項(xiàng)成為可選的。毫無疑問,這可以使最終的控件更為強(qiáng)壯些,但是我在本文中不再分析這些代碼。還應(yīng)該注意,就象在前面控件中一樣,我也添加了一個(gè)BuildItemList方法。
現(xiàn)在,你需要把這一客戶端代碼依附到復(fù)合控件的按鈕中。你可以在CreateChildControls方法的最后完成這一點(diǎn);并且,在此時(shí),完成子控件的初始化和構(gòu)建控件集合。在此,我僅向你展示相應(yīng)于一個(gè)按鈕的代碼(另外的按鈕代碼與此類似,省略)。
- string s_AddToLeft = "AddSelectedItemToList(document.all." +
- this.lstItemsOnRight.ClientID + ", document.all."
- + this.lstItemsOnLeft.ClientID + ", " +
- (this.AllowDuplicatesOnLeft ? "true" : "false") + "); ";
- string s_RemoveFromRight = "RemoveSelectedItemFromList(document.all." +
- this.lstItemsOnRight.ClientID + "); ";
- string s_BuildItemList = "BuildItemList(document.all." +
- this.lstItemsOnRight.ClientID + ", document.all.__" + lstItemsOnRight.ClientID + ");
- " + "BuildItemList(document.all." + this.lstItemsOnLeft.ClientID + ", document.all.__"
- + lstItemsOnLeft.ClientID + "); ";
- this.btnAdd.Attributes.Add("onclick", s_AddToLeft
- + " " + s_RemoveFromRight + " " + s_BuildItemList
- + " return false");
注意,我實(shí)現(xiàn)了在以前的控件中同樣的工作。我把JavaScript函數(shù)調(diào)用構(gòu)建成一字符串并且把它們依附到一個(gè)按鈕上。主要區(qū)別在于,既然這是一個(gè)包含其它控件的復(fù)合控件,那么你可能使用把代碼添加到onclick事件的Attributes.Add方法,這與在一個(gè)生成控件中把它放到一個(gè)棧上的方法形成對(duì)照。還要注意,我把多個(gè)功能放到onclick屬性中;而且,函數(shù)調(diào)用的最后返回false以便取消按鈕將執(zhí)行的任何回寄。
最后,代碼將在一個(gè)對(duì)Render重載的方法中初始化對(duì)客戶端函數(shù)BuildItemList的調(diào)用。這看起來很象我在 EnhancedListBox控件中向你介紹的那個(gè),在此不再重復(fù)。注意,在這個(gè)控件中,我注冊(cè)了兩個(gè)隱藏的文本域,每一個(gè)相應(yīng)于一個(gè)ListBox。
- protected override void OnPreRender(EventArgs e)
- {
- base.OnPreRender(e);
- if(Page != null)
- {
- Page.ClientScript.ReGISterHiddenField("__" + this.lstItemsOnRight.ClientID,
- "");
- Page.ClientScript.RegisterHiddenField("__" + this.lstItemsOnLeft.ClientID,
- "");
- Page.RegisterRequiresPostBack(this);
- }
- }
現(xiàn)在,C#復(fù)合控件構(gòu)建成功,能夠提供一些客戶端JavaScript,并且把它綁定到按鈕上。與以前一樣,你可以把它放到一個(gè)表單上并且使用它;但是,在你添加同步代碼之前,它仍將會(huì)遇到你在第一個(gè)控件中所遇到的問題—你可以前后移動(dòng)項(xiàng),但是一旦你初始化一個(gè)回寄(通過表單上的任何其它控件),該控件就會(huì)恢復(fù)到它回寄之前的狀態(tài)。
為了修改這個(gè)問題,你要實(shí)現(xiàn)你在第一個(gè)控件中所做的同樣的工作。然而,既然你在開發(fā)一個(gè)復(fù)合控件,而不是擴(kuò)展一個(gè)已經(jīng)現(xiàn)有的控件,那么你需要實(shí)現(xiàn)IPostBackDataHandler接口并且提供LoadPostData和 RaisePostDataChangedEvent方法的實(shí)現(xiàn)代碼。這些實(shí)現(xiàn)與前面的控件基本一致,除了你要實(shí)現(xiàn)兩個(gè) EnhancedListBox控件中的項(xiàng)集合的同步而不是只考慮一個(gè)控件外。并且與以前一樣,你需要確保你保存你的SelectedIndex位置;這樣以來,在你完成項(xiàng)集合的同步后你就可以把它們?cè)O(shè)置回去。還要注意,在第一個(gè)控件中,你重載了基控件的LoadPostData方法,因此在某處調(diào)用了它的基類?,F(xiàn)在,既然你要從頭編寫一個(gè)復(fù)合控件,那么就沒有基類可調(diào)用,而僅需提供你自己的方法實(shí)現(xiàn)。
這個(gè)控件的最后版本包含若干新的屬性:包括用來決定是否添加到一個(gè)列表中的項(xiàng)能夠被從另一個(gè)列表中刪除的屬性(如果一個(gè)列表將允許出現(xiàn)重復(fù)項(xiàng)的話);它還包含可擴(kuò)展的風(fēng)格化以實(shí)現(xiàn)最大化重用的目的,等等。
就這些。你已經(jīng)使用了可用于客戶端腳本中的隱藏的文本域來存儲(chǔ)列表框的狀態(tài)。在回寄期間,你使用隱藏文本域的內(nèi)容來與服務(wù)器端項(xiàng)集合重新同步。最終結(jié)果是一個(gè)漂亮的復(fù)合控件—允許你在沒有服務(wù)器回寄的情況下實(shí)現(xiàn)各列表項(xiàng)間的來回移動(dòng),而當(dāng)一個(gè)回寄真正發(fā)生時(shí)仍能夠保持這種變化。以上介紹C#復(fù)合控件構(gòu)建
【編輯推薦】