Как передать событие методу?
Я хотел бы создать метод, который принимает событие в качестве аргумента и добавляет eventHandler к нему для правильной обработки. Вот так:
У меня два события:
public event EventHandler Click;
public event EventHandler Click2;
Теперь я хотел бы передать конкретное событие моему методу, подобному этому (псевдокод):
public AttachToHandleEvent(EventHandler MyEvent)
{
MyEvent += Item_Click;
}
private void Item_Click(object sender, EventArgs e)
{
MessageBox.Show("lalala");
}
ToolStripMenuItem tool = new ToolStripMenuItem();
AttachToHandleEvent(tool.Click);
Возможно ли это?
Я заметил, что этот код работал нормально и вернулся к моему проекту и заметил, что когда я передаю событие, объявленное в моем классе, оно работает, но когда я передаю событие из другого класса, он все равно не работает.
Я получаю эту ошибку:
Событие 'System.Windows.Forms.ToolStripItem.Click' может появляться только с левой стороны of + = или - =
Ответы
Ответ 1
Мой первоначальный ответ был подходящим из класса, который определил событие, но с тех пор вы обновили свой вопрос, чтобы отразить, что вы хотите выполнить это из-за пределов определяющего класса, поэтому я поразил это.
Только класс, определяющий событие, может ссылаться на неявную переменную делегата, которую использует событие. Извне этого класса вы получаете доступ только к методам add
и remove
через +=
и -=
. Это означает, что вы не можете делать то, что вы просите, напрямую. Однако вы можете использовать функциональный подход.
class A{
public event EventHandler Event1;
public void TriggerEvent1(){
if(Event1 != null)
Event1(this, EventArgs.Empty);
}
}
class B{
static void HandleEvent(object o, EventArgs e){
Console.WriteLine("Woo-hoo!");
}
static void AttachToEvent(Action<EventHandler> attach){
attach(HandleEvent);
}
static void Main(){
A a = new A();
AttachToEvent(handler=>a.Event1 += handler);
a.TriggerEvent1();
}
}
Ответ 2
Я сделал это вот так:
public AttachToHandleEvent(Object obj, string EventName)
{
EventInfo mfi = obj.GetType().GetEvent(EventName);
MethodInfo mobj = mfi.GetAddMethod();
mobj.Invoke(obj, new object[] { Item_Click});
}
private void Item_Click(object sender, EventArgs e)
{
MessageBox.Show("lalala");
}
ToolStripMenuItem tool = new ToolStripMenuItem();
AttachToHandleEvent(tool "Click");
Спасибо всем за советы. Это решение не может быть выполнено без вашей помощи.
Ответ 3
Это невозможно. Вы можете использовать делегат вместо события, если это соответствует вашим потребностям.
Ответ 4
Просто напишите tool.Click += Item_Click;
Изменить: из MSDN "События могут быть вызваны только из класса или структуры, где они объявлены". То, что вы пытаетесь сделать, невозможно. Не могли бы вы подробнее рассказать о своих потребностях? Почему вы хотите передать событие в качестве параметра?
Ответ 5
delegate void doIt(object sender, object data);
event doIt OnDoIt;
void add(doIt theDel)
{
OnDoIt += theDel;
}
void doIt1(object a, object b)
{
}
void doIt2(object a, object b)
{
}
void add()
{
add(doIt1);
add(doIt2);
}
Ответ 6
Ваш вопрос подсказывает, что у вас есть некоторые механизмы:
Вы не можете передавать события!
Вы, скорее всего, хотите передать функцию в качестве параметра, поэтому вызывающий метод вызовет этот другой метод в какой-то момент. В техническом плане это делегат. Я предлагаю использовать уже определенный класс Action. Вот пример фрагмента:
void MyFunction (string otherArguments, Action onFinished){
...
if (onFinished != null)
onFinished.Invoke();
}
Приятная вещь в том, что при вызове MyFunction вы можете объявить действие с помощью встроенного синтаксиса:
MyFunction("my other argument", ()=>{
///do stuff here, which will be execuded when the action is invoked
});