前回の記事では、カスタム サーバー コントロール イベントの実装の基本概念を紹介しました。この記事では、代表的な例を通してコールバック イベントをキャプチャする方法を説明します。
1. ポストバック イベントのキャプチャを実装します。
サーバー コントロールがクライアントからポストバック イベントをキャプチャする必要があり、ポストバック イベントのサーバー側のイベント処理ロジックをカスタマイズしたい場合、コントロールは System.Web.UI.IPostBackEventHandler インターフェイスを実装する必要があります。インターフェース定義を以下に示します。
パブリック インターフェイス IPostBackEventHandler
{
void RaisePostBackEvent(stringeventArgument);
上記のコードに示されているように、IPostBackEventHandler インターフェイスにはメンバー メソッド RaisePostBackEvent が 1 つだけ含まれています
。
このメソッドにより、サーバー コントロールは、フォームがサーバーに送信されるときに発生するイベントを処理できるようになり、そのパラメーターのeventArgument は、イベント ハンドラーに渡されるオプションのイベント パラメーターを表します。開発者は、サーバー コントロールのポストバック プロセス中に実行されるロジックを RaisePostBackEvent メソッドに実装できます。通常、RaisePostBackEvent メソッドは 1 つ以上のサーバー側イベントを発生させます。次のコード スニペットは、サーバー上で Click イベントを発生させる RaisePostBackEvent 実装を示しています。
public void RaisePostBackEvent(String eventArgument)
{
OnClick(EventArgs.Empty);
、
サーバー コントロール クラスに IPostBackEventHandler インターフェイスを実装し、このインターフェイスのメンバー メソッドを実装するだけでは十分ではありません。開発者は他のものの実装にも注意を払う必要があります。以下に、ポストバック イベントをキャプチャするプロセスにおける 3 つの重要なポイントを示します。
まず、最も重要なことは、カスタム サーバー コントロール クラスは IPostBackEventHandler インターフェイスを実装し、インターフェイス メンバーの RaisePostBackEvent メソッドを実装する必要があることです。このプロセスについては上で説明しました。
次に、コントロールに UniqueID を割り当てます。
ポストバック イベントを UniqueID にするコントロールの name 属性値を定義することは、RaisePostBackEvent メソッドを正しく実装するための鍵の 1 つです。ポストバックがトリガーされると、ページ フレームワークは送信されるコンテンツを検索し、送信オブジェクトの名前が IPostBackEventHandler を実装するサーバー コントロールの UniqueID に対応するかどうかを判断します。対応する場合、ページ フレームワークはコントロールの RaisePostBackEvent メソッドを呼び出します。ここでの重要な点は、開発者がレンダリング ロジックでコントロールの name 属性に UniqueID を割り当てる必要があるということです。簡単なコード例を以下に示します。
protected オーバーライド void Render(HtmlTextWriter 出力)
{
Output.Write("<INPUT TYPE=submit name="+this.UniqueID+"Value='Click Me' />");
よう
に、コントロール レンダリング メソッド Render では、name 属性値が UniqueID であるボタンが表示されます。ポストバックを引き起こすコントロールの name 属性に UniqueID が割り当てられている場合にのみ、ポストバック イベントを正しくキャプチャできます。
3 番目に、イベント属性構造を実装します。
イベント属性構造は、イベントを実装するための最適化された方法です。紹介する前に、まず一般的なコントロール イベントの実装方法を見てみましょう。具体的なコードは以下の通りです。
...
パブリック クラス WebCustomControl:WebControl,IPostBackEventHandler{
//Click イベント デリゲートを宣言します。 public イベント EventHandler Click;
//RaisePostBackEvent メソッドを実装 void IPostBackEventHandler.RaisePostBackEvent(stringeventArgument) {
OnClick(EventArgs.Empty);
}
//OnClick イベント ハンドラを定義 protected virtual void OnClick(EventArgs e) {
if(Click != null) { Click(this,e) }
}
...
1. Click イベント デリゲートを定義します。 2. コントロール クラスは IPostBackEventHandler インターフェイスを実装します。このインターフェイスでは、インターフェイス メンバー メソッド RaisePostBackEvent を実装するときにイベント ハンドラー OnClick が定義されます
。
;3. OnClick イベント ハンドラーを実装します。上記の実装方法はシンプルで使いやすいですが、実行効率が低いという欠点があります。特に、クラス内で複数のイベントがトリガーされると、オーバーヘッドが増加し、多くのサーバー リソースが無駄になり、最終的には運用効率の低下につながります。
上記の問題を解決するために、最適化されたイベント実装メソッドとイベント属性構造が以下に導入されます。この構造では、単純なデリゲート リストを提供する System.ComponentModel.EventHandlerList クラスを使用します。このクラスが提供する関連メソッドを使用することにより、開発者はコントロールのイベント ハンドラー デリゲート リストを柔軟に操作できます。たとえば、コントロールの Click イベントは、次のようなイベント属性構造を使用します。
protected static readonly object EventClick = new object();
パブリック イベント EventHandler Click{
追加 {
Events.AddHandler(EventClick,value);
}
取り除く {
Events.RemoveHandler(EventClick,value);
}
、
まず Click イベント デリゲート オブジェクトを定義する必要があります。各イベントは 1 回だけ作成されるため、静的かつ読み取り専用として宣言する必要があります。次に、プロパティ構造体の AddHandler メソッドと RemoveHandler メソッドを使用して、イベント ハンドラーのデリゲート リストを操作します。ページが Click イベントを呼び出すと、コントロールの EventHandlerList コレクションからハンドラーが追加または削除されます。この実装方法は複数のイベントの宣言処理において通常の実装方法よりも効率が良いため、非常におすすめの方法です。
さらに、OnClick メソッドの実装中にイベント属性を使用する場合、デリゲートを EventHandlerList から取得し、EventHandler 型に変換する必要があります。
protected virtual void OnClick(EventArgs e){
EventHandler clickHandler = (EventHandler)Events[EventClick];
if(clickHandler != null) {
clickHandler(this,e);
}
:
イベント属性構造は VB.NET 言語には適用できず、C# などの言語にのみ適用できます。
2. 代表的な用途
正直に言うと、ポストバック イベントのキャプチャに関する上記の理論的な説明は、サーバー コントロール イベントを実装したことがない読者にとってはやや理解しにくいものです。このため、このセクションでは、典型的な例を使用して、リターン イベントをキャプチャする実装方法を具体的に説明します。
この例では、カスタム サーバー コントロール WebCustomControl を実装します。このコントロールはボタンとして表示されますが、Button クラスを継承しません。ボタンがクリックされると、コントロールによってポストバックが発生し、サーバーは返されたクリック イベントを自動的にキャプチャし、Click イベントをトリガーし、対応するイベント ハンドラーを実行します。以下は、サーバー コントロール実装のソース コードです。
システムを使用する; System.Collections.Generic を使用します。 System.ComponentModel を使用します。 System.Text を使用します。 System.Web を使用します。 System.Web.UI を使用します。 System.Web.UI.WebControls を使用します。 名前空間 WebControlLibrary{ [DefaultEvent("Click")] [ToolboxData("<{0}:WebCustomControl runat=server></{0}:WebCustomControl>")] パブリック クラス WebCustomControl : WebControl、IPostBackEventHandler { //Click イベントデリゲートオブジェクトを定義します private static readonly object EventClick = new object(); //クリックイベントのプロパティを実装 [Description("クリックイベントのプロパティ"), カテゴリ("アクション") ] パブリック イベント EventHandler { をクリックします 追加 { Events.AddHandler(EventClick, value); } 取り除く { Events.RemoveHandler(EventClick, value); } } // コントロールのレンダリング メソッド RenderContents をオーバーライドします。 protected override void RenderContents(HtmlTextWriter 出力) { Output.Write("<input type='submit' name= + this.UniqueID + " value=クリックしてください/>"); } //イベントメソッドを実装 protected virtual void OnClick(EventArgs e) { EventHandler clickHandler = (EventHandler)Events[EventClick]; if (clickHandler != null) { clickHandler(this, e); } } // IPostBackEventHandler インターフェイスを実装 member void IPostBackEventHandler.RaisePostBackEvent(stringeventArgument) { OnClick(EventArgs.Empty); } } } |
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <%@ 登録 TagPrefix="cc" 名前空間="WebControlLibrary" Assembly="WebControlLibrary" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="サーバー"> void wcc1_Click(オブジェクト送信者, EventArgs e) { message.Text = "上のボタンをクリックしました"; } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="サーバー"> <title>ポストバック イベントをキャプチャする</title> </head> <本文> <form id="form1" runat="server"> <中央> <cc:WebCustomControl ID="wcc1" runat="server" OnClick="wcc1_Click" /> <br /> <br /> <asp:Label ID="メッセージ" runat="server"></asp:Label> </center> </form> </body> </html> |
図 1 ページの初期化レンダリング 図 2 ボタンをクリックした後の効果 |
//属性 AutoPostBack を定義します public bool AutoPostBack{ セット { this._autoPostBack = 値; } 得る { これを返します。_autoPostBack; } } //Render メソッドに Page.GetPostBackEventReference() メソッドを追加します protected override void Render(HtmlTextWriter 出力){ ... if(this.AutoPostBack) { Writer.WriteAttribute("ontextchanged","javascript:" + Page.GetPostBackEventReference(this)); } ... } |