たまに動的にイベントを追加したり、削除したりしたいときがあります。
イベントを動的に追加・削除するには以下のクラスを利用します。
- System.Delegate
- System.Reflection.EventInfo
面倒なのが、実際にイベントを追加したり削除したりする際です。
いくら文字列で処理が実装されているメソッド名をもっていても
MethodInfoでは追加できません。一旦、該当するイベントのイベントハンドラデリゲート
でラップする必要があります。
動的にデリゲートを作成するには、以下のようにします。
Delegate d = Delegate.CreateDelete(イベントハンドラのタイプ, 処理メソッドを持つオブジェクト, メソッド名もしくはMethodInfo);
上記のを組み合わせると動的にイベントを追加・削除できます。
以下サンプルです。
// vim:set ts=4 sw=4 et ws is nowrap ft=cs: using System; using System.Reflection; using System.Windows.Forms; namespace Gsf.Demo{ public class DemoForm : Form{ Button btn1; Button btn2; Button btn3; public DemoForm(){ InitializeComponent(); InitializeEventBinding(); } protected void InitializeComponent(){ SuspendLayout(); Text = "動的にイベントを追加するサンプル"; btn1 = new Button(); btn1.Text = "イベント追加"; btn2 = new Button(); btn2.Text = "イベント削除"; btn3 = new Button(); btn3.Text = "イベント実行"; FlowLayoutPanel p = new FlowLayoutPanel(); p.Controls.AddRange(new []{btn1, btn2, btn3}); Controls.Add(p); ResumeLayout(); } protected void InitializeEventBinding(){ // // 通常のイベントバインディング. // btn1.Click += AddEvent; } public void AddEvent(object sender, EventArgs e){ // // イベントを動的に追加する。 // Type handlerType = typeof(EventHandler); Action<Control, string> registEvent = (ctl, methodName) => { // // 該当するイベントのイベントハンドラを構築し、追加する。 // (今回はサンプルなのでmethodNameに指定したメソッドはスコープをpublicにしています。 // 実際は、フォーム内に定義されているメソッドはprivateなどで定義するべきです。) // Delegate eventMethod = Delegate.CreateDelegate(handlerType, this, this.GetType().GetMethod(methodName)); ctl.GetType().GetEvent("Click").AddEventHandler(ctl, eventMethod); }; registEvent(btn2, "RemoveEvent"); registEvent(btn3, "ExecuteEvent"); } public void RemoveEvent(object sender, EventArgs e){ // // イベントを動的に削除する。 // Type handlerType = typeof(EventHandler); Action<Control, string> removeEvent = (ctl, methodName) => { // // 該当するイベントのイベントハンドラを構築し、削除する。 // (今回はサンプルなのでmethodNameに指定したメソッドはスコープをpublicにしています。 // 実際は、フォーム内に定義されているメソッドはprivateなどで定義するべきです。) // Delegate eventMethod = Delegate.CreateDelegate(handlerType, this, this.GetType().GetMethod(methodName)); ctl.GetType().GetEvent("Click").RemoveEventHandler(ctl, eventMethod); }; removeEvent(btn2, "RemoveEvent"); removeEvent(btn3, "ExecuteEvent"); } public void ExecuteEvent(object sender, EventArgs e){ MessageBox.Show("Execute Event."); } static void Main(){ Application.EnableVisualStyles(); Application.Run(new DemoForm()); } } }
上記のサンプルをコンパイルして実行すると、ボタンが表示されます。
イベントを追加ボタンを押下するまでは、その他のボタンを押下しても
何も反応しません。イベント追加ボタン押下後にイベント実行ボタンを
押下するとメッセージボックスが表示されます。
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ