컨트롤에서 새 이벤트 처리기를 만들려면 다음을 수행하십시오.
c.Click += new EventHandler(mainFormButton_Click);
아니면 이거
c.Click += mainFormButton_Click;
이벤트 핸들러를 제거하려면 다음을 수행하십시오.
c.Click -= mainFormButton_Click;
그러나 이벤트에서 모든 이벤트 핸들러를 어떻게 제거합니까?
답변
MSDN 포럼 에서 해결책을 찾았습니다 . 아래 샘플 코드는에서 모든 Click
이벤트를 제거합니다 button1
.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Click += button1_Click;
button1.Click += button1_Click2;
button2.Click += button2_Click;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello");
}
private void button1_Click2(object sender, EventArgs e)
{
MessageBox.Show("World");
}
private void button2_Click(object sender, EventArgs e)
{
RemoveClickEvent(button1);
}
private void RemoveClickEvent(Button b)
{
FieldInfo f1 = typeof(Control).GetField("EventClick",
BindingFlags.Static | BindingFlags.NonPublic);
object obj = f1.GetValue(b);
PropertyInfo pi = b.GetType().GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
list.RemoveHandler(obj, list[obj]);
}
}
}
답변
너희들은이 길을 너무 힘들게 만들고있다. 이 쉬운 일이다 :
void OnFormClosing(object sender, FormClosingEventArgs e)
{
foreach(Delegate d in FindClicked.GetInvocationList())
{
FindClicked -= (FindClickedHandler)d;
}
}
답변
모든 이벤트 핸들러 제거 에서 :
이벤트를 단순히 널로 설정할 수 없기 때문에 직접 아니오.
간접적으로 실제 이벤트를 비공개로 만들고 주변에 추가 / 삭제되는 모든 대리자를 추적하는 속성을 만들 수 있습니다.
다음을 수행하십시오.
List<EventHandler> delegates = new List<EventHandler>(); private event EventHandler MyRealEvent; public event EventHandler MyEvent { add { MyRealEvent += value; delegates.Add(value); } remove { MyRealEvent -= value; delegates.Remove(value); } } public void RemoveAllEvents() { foreach(EventHandler eh in delegates) { MyRealEvent -= eh; } delegates.Clear(); }
답변
허용 된 답변이 가득 찼습니다. {add;로 선언 된 이벤트에는 작동하지 않습니다. 없애다;}
작동 코드는 다음과 같습니다.
public static void ClearEventInvocations(this object obj, string eventName)
{
var fi = obj.GetType().GetEventField(eventName);
if (fi == null) return;
fi.SetValue(obj, null);
}
private static FieldInfo GetEventField(this Type type, string eventName)
{
FieldInfo field = null;
while (type != null)
{
/* Find events defined as field */
field = type.GetField(eventName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null && (field.FieldType == typeof(MulticastDelegate) || field.FieldType.IsSubclassOf(typeof(MulticastDelegate))))
break;
/* Find events defined as property { add; remove; } */
field = type.GetField("EVENT_" + eventName.ToUpper(), BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
break;
type = type.BaseType;
}
return field;
}
답변
존재하지 않는 이벤트 핸들러를 삭제해도 아무런 해가 없습니다. 따라서 어떤 핸들러가 있는지 아는 경우 간단히 모든 핸들러를 삭제할 수 있습니다. 방금 비슷한 경우가있었습니다. 경우에 따라 도움이 될 수 있습니다.
처럼:
// Add handlers...
if (something)
{
c.Click += DoesSomething;
}
else
{
c.Click += DoesSomethingElse;
}
// Remove handlers...
c.Click -= DoesSomething;
c.Click -= DoesSomethingElse;
답변
실제로이 방법을 사용하고 있으며 완벽하게 작동합니다. I이었다 Aeonhack에 의해 작성된 코드에 의해 ‘영감’ 여기 .
Public Event MyEvent()
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If MyEventEvent IsNot Nothing Then
For Each d In MyEventEvent.GetInvocationList ' If this throws an exception, try using .ToArray
RemoveHandler MyEvent, d
Next
End If
End Sub
MyEventEvent 필드는 숨겨져 있지만 존재합니다.
디버깅 d.target
하면 객체가 실제로 이벤트를 처리하는 방법을 볼 수 있습니다.d.method
방법 그 방법을 볼 수 있습니다. 당신은 그것을 제거해야합니다.
잘 작동합니다. 이벤트 핸들러로 인해 더 이상 GC되지 않는 오브젝트가 없습니다.
답변
나는 여기에 표시된 모든 완벽한 솔루션을 싫어했고, 지금 혼합하고 테스트했으며 모든 이벤트 핸들러에서 일했습니다.
public class MyMain()
public void MyMethod() {
AnotherClass.TheEventHandler += DoSomeThing;
}
private void DoSomething(object sender, EventArgs e) {
Debug.WriteLine("I did something");
AnotherClass.ClearAllDelegatesOfTheEventHandler();
}
}
public static class AnotherClass {
public static event EventHandler TheEventHandler;
public static void ClearAllDelegatesOfTheEventHandler() {
foreach (Delegate d in TheEventHandler.GetInvocationList())
{
TheEventHandler -= (EventHandler)d;
}
}
}
쉬운! Stephen Punak에게 감사합니다.
나는 일반적인 로컬 메소드를 사용하여 델리게이트를 제거하고 다른 델리게이트가 설정 될 때 로컬 메소드가 다른 경우에 호출 되었기 때문에 그것을 사용했습니다.