定制AjaxControlToolkit(1):使一个CalendarExtender对应N个TextBox
其實像AutoCompleteExtender之類的其它擴展也是與此類似,這里只是用CalendarExtender舉例子了。
AjaxControlToolkit確實是個好東西,但是我實在不明白設計者是出于什么目的一定要把它捆在某一個文本框上,使得這組控件變得很難用。對日期控件來說,可能很多人用過梅花雨做的那個日期控件,那個控件確實很好用,而且其setday(this)這樣的調用方式也非常簡單明了,但是它存在許多問題(跟主題無關,不再細說),為了說服我的同事轉用CalendarExtender,我決定想個辦法使CalendarExtender也能像梅花雨日期控件一樣簡單好用。
由于AjaxControlToolkit天生的設計,不修改AjaxControlToolkit.dll是絕不可能達到目的的,不過好在微軟提供了源代碼(不知道應該說感謝微軟,還是應該說感謝多年來堅持呼吁開源的人士- -!),所以修改dll變得一點也不復雜了。
首先,在結構上CalendarBehavior類繼承自BehaviorBase類, BehaviorBase又繼承自Sys.UI.Behavior類,這幾個類中,CalendarBehavior和BehaviorBase類存在于AjaxControlToolkit項目中,可以直接修改,但是Sys.UI.Behavior存在于.NET Framework附帶的System.Web.Extension.dll中,所以修改只能止于BehaviorBase了,要修改Sys.UI.Behavior的話,代價太大,不考慮。
但是,偏偏把擴展綁定到一個固定的控件上這個規則,就是Sys.UI.Behavior定義的!在這個類的構造函數中,把目標文本框傳入,此后只能從子類調用繼承的方法get_element()來獲取這個文本框,而無法去更改它,因為沒有基類Sys.UI.Behavior的實例,所以訪問它的私有屬性自然也是不可能的事。本來,如果給基類增加一個set_element()方法,既簡單效率又最高,但是偏偏這個最佳途徑被堵死了。于是只能退而求其次,從CalendarBehavior類身上做文章。
為了使目標文本框可以動態地變化,首先給CalendarBehavior類增加一個私有屬性:
this._element?=?element;然后要有讀取它的公共方法:
get_targetElement:?function()?{????????return?this._element;
}
把CalendarBehavior類中所有的get_element()方法替換成get_targetElement()方法,就使得Sys.UI.Behavior沒有用武之地了,現在只要再有一個改變_element私有屬性的方法即可大功靠成。
但是這個set方法并不是這么簡單。首先,在構造CalendarExtender的時候,向目標文本框附加了好幾個事件,現在既然要換文本框,原來的宿主文本框上綁定的事件必須被解除,并且把它們附加到新的文本框上;其次,CalendarBehavior有一個_popupBehavior私有屬性,它是一個PopupExtender類的一個實例,PopupBehavior類實現了彈出div,定位擴展控件等功能,包括AutoCompleteExtender等其它彈出式控件都使用這個類的功能。CalendarBehavior在構造的時候,_popupBehavior也被按照第一個文本框的參數進行了構造,現在雖然目標文本框換了,但是_popupBehavior仍然是相對于第一個文本框而言的,需要將這個對象按照新的目標文本框重新構建;與_popupBehavior類似的還包括其它幾個私有屬性,set方法的代碼如下:
????set_targetElement:?function(element)?{????????///?<summary>
????????///?switch?target?textbox
????????///?</summary>
????????if?(this._element.id?==?element.id)
????????????return;
????????$common.removeHandlers(this.get_targetElement(),?this._element$delegates);
????????$addHandlers(element,?this._element$delegates);
????????this._element?=?element;
????????this._textbox?=?AjaxControlToolkit.TextBoxWrapper.get_Wrapper(element);
????????if?(this._popupBehavior)?{
????????????this._popupBehavior.dispose();
????????????this._popupBehavior?=?null;
????????}
????????if?(this._container)?{
????????????if?(this._container.parentNode)?{?//?added?this?check?before?calling?removeChild?WI:?8486
????????????????this._container.parentNode.removeChild(this._container);
????????????}
????????????this._container?=?null;
????????}
????????if?(this._popupDiv)?{
????????????$common.removeHandlers(this._popupDiv,?this._popup$delegates);
????????????this._popupDiv?=?null;
????????}
????},
其中,第一句先判斷要設置的目標控件是不是與當前控件一樣,是非常重要的一步,否則會造成無謂的效率浪費,而且這一比較幾乎不需要什么代價。
經過這樣的包裝后,項目中就可以調用set_targetElement()方法進行動態切換目標文本框了,因為我們的項目使用母版頁,所以我在母版頁中增加了這樣一個
函數:
function?setday(element)?{????var?ce?=?$find("pm_ce1");
????ce.set_targetElement(element);
????ce.show();
}
其中,pm_ce1是ajaxToolkit:CalendarExtender的BehaviorID,我在母版頁中直接放了一個CalendarExtender,這樣內容頁就可以完全忽略CalendarExtender的細節,像調用梅花雨日期控件一樣了:
<asp:TextBox?ID="txt1"?runat="server"?onclick="setday(this);"?></asp:TextBox>?
順便貼一個CalendarExtender的樣式,這是從一個國外的網站上抄來的,忘了是哪個網站了,估計作者也看不懂中文,不至于來罵我一頓。:)
.cal_Theme1?.ajax__calendar_container{}{
????background-color:?#e2e2e2;
????border:?solid?1px?#cccccc;
}
.cal_Theme1?.ajax__calendar_header
{}{
????background-color:?#ffffff;
????margin-bottom:?4px;
}
.cal_Theme1?.ajax__calendar_title,?.cal_Theme1?.ajax__calendar_next,?.cal_Theme1?.ajax__calendar_prev
{}{
????color:?#004080;
????padding-top:?3px;
}
.cal_Theme1?.ajax__calendar_body
{}{
????background-color:?#e9e9e9;
????border:?solid?1px?#cccccc;
}
.cal_Theme1?.ajax__calendar_dayname
{}{
????text-align:?center;
????font-weight:?bold;
????margin-bottom:?4px;
????margin-top:?2px;
}
.cal_Theme1?.ajax__calendar_day
{}{
????text-align:?center;
}
.cal_Theme1?.ajax__calendar_hover?.ajax__calendar_day,?.cal_Theme1?.ajax__calendar_hover?.ajax__calendar_month,?.cal_Theme1?.ajax__calendar_hover?.ajax__calendar_year,?.cal_Theme1?.ajax__calendar_active
{}{
????color:?#004080;
????font-weight:?bold;
????background-color:?#ffffff;
}
.cal_Theme1?.ajax__calendar_today
{}{
????font-weight:?bold;
}
.cal_Theme1?.ajax__calendar_other,?.cal_Theme1?.ajax__calendar_hover?.ajax__calendar_today,?.cal_Theme1?.ajax__calendar_hover?.ajax__calendar_title
{}{
????color:?#bbbbbb;
}
?
?指定CalendarExtender的CssClass屬性等于cal_Theme1即可。
這個主題運行時的截圖:
?
?
轉載于:https://www.cnblogs.com/Moosdau/archive/2009/04/08/1431962.html
總結
以上是生活随笔為你收集整理的定制AjaxControlToolkit(1):使一个CalendarExtender对应N个TextBox的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何读时序
- 下一篇: 使用XMLSerializerNames