在之前講的幾個例子中,使用的是最普通的定義事件方法,比如KingTextBox中事件是這樣定義的:
/// <summary>
/// 獲得本書更多內容,請看:
/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx
/// </summary>
public event EventHandler TextChanged;
PRotected virtual void OnTextChanged(EventArgs e)
{
if (TextChanged != null)
{
TextChanged(this, e);
}
}
在復合控件中,事件一般比較多,如果仍然基于以上普通事件的實現方法來定義事件,就會定義許多事件委托實現對象,導致占用較多內存存儲。
在這種情況下,則應該通過System.ComponentModel.EventHandlerList集合類來保存事件,原因是使用此類在多個事件的聲明過程中比普通的實現方法效率高。EventHandlerList類提供一個簡單的委托列表來添加(Events.AddHandler)和刪除(Events.RemoveHandler)委托,在Control基類中已經定義好了EventHandlerList類型的對象Events,因此可以直接通過base.Events訪問事件列表對象。
下面利用Events集合對象存儲事件,修改一下KingTextBox控件的事件聲明/調用部分,為了保留KingTextBox現有功能,新增一個控件示例,控件名稱為KingTextBoxUseEvents。事件部分的代碼為:
/// <summary>
/// 獲得本書更多內容,請看:
/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx
/// </summary>
private static readonly object TextChangedKeyObject = new object();
public event EventHandler TextChanged
{
add
{
base.Events.AddHandler(KingTextBoxUseEvents.TextChangedKeyObject, value);
}
remove
{
base.Events.RemoveHandler(KingTextBoxUseEvents.TextChangedKeyObject,
value);
}
}
protected virtual void OnTextChanged(EventArgs e)
{
EventHandler handler = base.Events[KingTextBoxUseEvents.TextChanged
KeyObject] as EventHandler;
if (handler != null)
{
handler(this, e);
}
}
以上代碼首先定義了一個Object對象TextChangedKeyObject,用于當存儲事件到Events列表時,作為TextChanged事件的Key,其對應Value為即為事件方法體。接下來定義了一個事件委托類型的TextChanged屬性,其內容包括一個add和一個remove子句,在這兩個子句中分別完成注冊和釋放事件功能。最后的OnTextChanged方法也稍微變了一下,增加了從base.Events事件列表中根據TextChangedKeyObject鍵得到事件句柄的代碼語句,如果取得的句柄handler不為null,即可引發開發人員注冊的事件。
控件KingTextBoxUseEvents代碼也比較簡單,下面也把它的完整代碼展示出來:
/// <summary>
/// 獲得本書更多內容,請看:
/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx
/// </summary>
[DefaultProperty("Text")]
[ToolboxData("<{0}:KingTextBoxUseEvents runat=server></{0}:KingTextBoxUseEvents>")]
public class KingTextBoxUseEvents : Control, ipostBackDataHandler
{
public KingTextBoxUseEvents()
{
}
/// <summary>
/// 設置或獲取顯示文本
/// </summary>
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}
set
{
ViewState["Text"] = value;
}
}
/// <summary>
/// 生成呈現HTML格式標記
/// </summary>
/// <param name="writer"></param>
protected override void Render(HtmlTextWriter writer)
{
StringBuilder sb = new StringBuilder();
sb.Append("<input type=/"text/" name=");
sb.Append("/"" + UniqueID + "/"");
sb.Append(" value=");
sb.Append("/"" + HttpUtility.HtmlEncode(Text) + "/"");
sb.Append(" />");
writer.Write(sb.ToString());
}
public virtual bool LoadPostData(string postDataKey, NameValueCollection
postCollection)
{
string strOldValue = Text;
string strNewValue = postCollection[this.UniqueID];
if( strOldValue == null || ( strOldValue != null && !strOldValue.Equals
(strNewValue)))
{
this.Text = strNewValue;
return true;
}
return false;
}
public virtual void RaisePostDataChangedEvent()
{
OnTextChanged(EventArgs.Empty);
}
//高效事件
private static readonly object TextChangedKeyObject = new object();
public event EventHandler TextChanged
{
add
{
base.Events.AddHandler(KingTextBoxUseEvents.TextChangedKeyObject, value);
}
remove
{
base.Events.RemoveHandler(KingTextBoxUseEvents.TextChanged
KeyObject, value);
}
}
protected virtual void OnTextChanged(EventArgs e)
{
EventHandler handler =base.Events[KingTextBoxUseEvents.TextChanged KeyObject] as EventHandler;
if (handler != null)
{
handler(this, e);
}
}
}
KingTextBoxUseEvents控件與KingTextBox功能完全相同,應用方法也相同。另外,事件的委托和參數對象也可以自定義,下一節就講一下如何定制自己的委托和事件對象。
新聞熱點
疑難解答