トップ回答者
イベントの削除・入替方法は?

質問
-
毎度、お世話に成ります。
任意の関数をボタンのイベントに割り当てる事に挑んでいるのですが(実際にはボタンに割り当てる関数を外部で制御したい)
イベントの削除方法がわからずに悩んでいます。
サンプルコードです。
コード ブロックusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.IO;
using System.Reflection;namespace Test.TestForms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}public void Action1_Click(object sender, EventArgs e)
{
MessageBox.Show("1");
}public void Action2_Click(object sender, EventArgs e)
{
MessageBox.Show("2");
}public void Action3_Click(object sender, EventArgs e)
{
MessageBox.Show("3");
}public void Action4_Click(object sender, EventArgs e)
{
MessageBox.Show("4");
}private void Form1_Load(object sender, EventArgs e)
{
Type type = this.GetType();MethodInfo[] infos = type.GetMethods();
// Action?_Clickの名称をlistBox1に追加
foreach (MethodInfo info in infos)
{
if (info.Name.IndexOf("Action") >= 0 && info.Name.IndexOf("Click") > 0)
{
listBox1.Items.Add(info.Name);
}
}
}private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string s = listBox1.Items[listBox1.SelectedIndex] as string;Type type = this.GetType();
MethodInfo info = type.GetMethod(s);
Delegate Event = Delegate.CreateDelegate(typeof(EventHandler), this, s);// listBox1 で選択している名称のイベントを Button1 の Click に登録
// 本当は此処で Button1.Click -= (????) で登録されているイベントを全部削除したい
Button1.Click += Event as EventHandler;
}
}
}実際にはイベント名をDB等に複数登録して置いてボタンをイベントランチャー的に使いたいのですが、Button1.Click に登録されているイベントが何が登録されているか判らないので、Button1.Click に登録されているものを全削除したいのです。
何かヒントになるようなアドバイス頂けないでしょうか?
よろしくお願い致します。
回答
-
eventフィールドは+=か-=の操作しかできません。
既存のeventを全て削除するためには、別途それらを記憶するフィールド変数が必要となると思います。
今回ボタン1個につき1個のイベントを割り当てるという趣旨であれば、次のような形でどうでしょうか?
コード ブロックprivate void Form1_Load(object sender, EventArgs e)
{
CurrentEvent = new EventHandler(Action2_Click);
}
private EventHandler CurrentEvent;
private void button1_Click(object sender, EventArgs e)
{
if (CurrentEvent != null)
{
CurrentEvent(sender, e);
}
}CurrentEventの値を差し替える形です。
-
Nishizaka さんからの引用 何かヒントになるようなアドバイス頂けないでしょうか?
ちょっと前にVBの方にこんな過去スレッドがありました。
MSDN フォーラム > Visual Studio > Visual Basic フォーラム > イベントの存在チェック
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=2091544&SiteID=7
ご参考になりませんか。
-
IIJIMAS さん コメントありがとうございます。
IIJIMAS さんからの引用 MSDN フォーラム > Visual Studio > Visual Basic フォーラム > イベントの存在チェック
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=2091544&SiteID=7
すごく参考に成りました。ご紹介頂いたスレッドの
http://www.technewsgroups.net/group/microsoft.public.dotnet.general/topic4196.aspx
このEventDatum クラスを使い(エベント名を参照するプロパティを追加して)
コード ブロックpublic class EventDatum
{
|public string EventName
{
get { return _event.Method.Name; }
}}
listBox1_SelectedIndexChanged を下記の様に書き換えることで
コード ブロックprivate void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// ターゲットイベントの削除EventDescriptorCollection events = TypeDescriptor.GetEvents(this);
foreach (System.ComponentModel.EventDescriptor myEvent in events)
{
EventDatum ed = EventDatum.Create(Button1, myEvent);
if (ed == null) continue;
if (ed.EventName.IndexOf("Action") >= 0 && ed.EventName.IndexOf("Click") > 0)
{
ed.Unwire(Button1);
}
}string s = listBox1.Items[listBox1.SelectedIndex] as string;
Delegate Event = Delegate.CreateDelegate(typeof(EventHandler), this, s);Button1.Click += Event as EventHandler;
}イベント関数名に一貫性を持たせれば、可能な事がわかりました。
アドバイス、ありがとうございました。
すべての返信
-
eventフィールドは+=か-=の操作しかできません。
既存のeventを全て削除するためには、別途それらを記憶するフィールド変数が必要となると思います。
今回ボタン1個につき1個のイベントを割り当てるという趣旨であれば、次のような形でどうでしょうか?
コード ブロックprivate void Form1_Load(object sender, EventArgs e)
{
CurrentEvent = new EventHandler(Action2_Click);
}
private EventHandler CurrentEvent;
private void button1_Click(object sender, EventArgs e)
{
if (CurrentEvent != null)
{
CurrentEvent(sender, e);
}
}CurrentEventの値を差し替える形です。
-
Nishizaka さんからの引用 何かヒントになるようなアドバイス頂けないでしょうか?
ちょっと前にVBの方にこんな過去スレッドがありました。
MSDN フォーラム > Visual Studio > Visual Basic フォーラム > イベントの存在チェック
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=2091544&SiteID=7
ご参考になりませんか。
-
-
IIJIMAS さん コメントありがとうございます。
IIJIMAS さんからの引用 MSDN フォーラム > Visual Studio > Visual Basic フォーラム > イベントの存在チェック
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=2091544&SiteID=7
すごく参考に成りました。ご紹介頂いたスレッドの
http://www.technewsgroups.net/group/microsoft.public.dotnet.general/topic4196.aspx
このEventDatum クラスを使い(エベント名を参照するプロパティを追加して)
コード ブロックpublic class EventDatum
{
|public string EventName
{
get { return _event.Method.Name; }
}}
listBox1_SelectedIndexChanged を下記の様に書き換えることで
コード ブロックprivate void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// ターゲットイベントの削除EventDescriptorCollection events = TypeDescriptor.GetEvents(this);
foreach (System.ComponentModel.EventDescriptor myEvent in events)
{
EventDatum ed = EventDatum.Create(Button1, myEvent);
if (ed == null) continue;
if (ed.EventName.IndexOf("Action") >= 0 && ed.EventName.IndexOf("Click") > 0)
{
ed.Unwire(Button1);
}
}string s = listBox1.Items[listBox1.SelectedIndex] as string;
Delegate Event = Delegate.CreateDelegate(typeof(EventHandler), this, s);Button1.Click += Event as EventHandler;
}イベント関数名に一貫性を持たせれば、可能な事がわかりました。
アドバイス、ありがとうございました。