How to Remove All Event Handlers from an Event

How to remove all event handlers from an event

I found a solution on the MSDN forums. The sample code below will remove all Click events from 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]);
}
}

How to remove all eventhandler

Simply set the event to null:

this.Something = null;

It will unregister all event handlers.

Is it possible to remove all event handlers of a given element in javascript?

http://www.quirksmode.org/js/events_advanced.html - "Which event handlers are registered?" - it seems it's not possible without DOM 3 level :-(

EDIT: I've come up with this code. It suits my needs. Maybe it will be helpful for someone else.

Javascript:

function DomLib() {


}


/**
* Based on: http://ejohn.org/blog/flexible-javascript-events/
* Function that register event and enables it to be removed without explicitly giving the function definition
*/
DomLib.prototype.regEventEx = function (el, eventName, funct) {

if (el.attachEvent) {
el['e'+eventName+funct] = funct;
el[eventName+funct] = function(){el['e'+eventName+funct](window.event);}
el.attachEvent( 'on'+eventName, el[eventName+funct] );
} else {
el.addEventListener(eventName, funct, false);
}

if(!el.eventHolder) el.eventHolder = [];
el.eventHolder[el.eventHolder.length] = new Array(eventName, funct);
}

DomLib.prototype.removeEvent = function (obj, type, fn) {
if (obj.detachEvent) {
obj.detachEvent( 'on'+type, obj[type+fn] );
obj[type+fn] = null;
} else {
obj.removeEventListener( type, fn, false );
}
}


DomLib.prototype.hasEventEx = function (el, eventName, funct) {

if (!el.eventHolder) {
return false;
} else {
for (var i = 0; i < el.eventHolder.length; i++) {
if (el.eventHolder[i][0] == eventType && String(el.eventHolder[i][1]) == String(funct)) {
return true;
}
}
}
return false;
}

/**
* @return - returns true if an event was removed
*/
DomLib.prototype.removeEventsByTypeEx = function (el, eventType) {

if (el.eventHolder) {

var removed = 0;
for (var i = 0; i < el.eventHolder.length; i++) {
if (el.eventHolder[i][0] == eventType) {
this.removeEvent(el, eventType, el.eventHolder[i][1]);
el.eventHolder.splice(i, 1);
removed++;
i--;
}
}

return (removed > 0) ? true : false;
} else {
return false;
}
}

Testing HTML page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Expires" content="Fri, Jan 01 1900 00:00:00 GMT">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Lang" content="en">
<meta name="author" content="">
<meta http-equiv="Reply-to" content="@.com">
<meta name="generator" content="PhpED 5.8">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="creation-date" content="01/01/2009">
<meta name="revisit-after" content="15 days">
<title>DomLibTest</title>
<link rel="stylesheet" type="text/css" href="my.css">
<!-- FILL IN: Location of your jQuery library -->
<script type="text/javascript" src="jQuery/jQuery-current.js"></script>
<!-- FILL IN: Plugin for debugging ... http://www.ecitadel.net/blog/2009/12/08/developing-jquery-use-dump-instead-alert -->
<script type="text/javascript" src="jQuery/jQuery.dump.js"></script>
<script type="text/javascript" src="DomLib.js"></script>
</head>
<body>

<div id="testElem-1"></div>
<script type="text/javascript">
<!--

var domLib = new DomLib();

function removeTest(el) {

var funct = function() { alert("#1: How Are You?");};
var funct2 = function() { alert("#2: How Are You?");};

domLib.regEventEx(el, "click", funct);
domLib.regEventEx(el, "mousemove", funct2);
domLib.regEventEx(el, "mousemove", funct2);
domLib.regEventEx(el, "mousemove", funct2);

$.dump(el.eventHolder);
domLib.removeEventsByTypeEx(el, "mousemove");
$.dump(el.eventHolder);
}

removeTest(document.getElementById('testElem-1'));

-->
</script>
</body>
</html>

How to remove all event handlers from an event?

It is the lambda expression that is getting you into trouble here. Don't dig a deeper hole, just use AddressOf and a private method instead so you can trivially use the RemoveHandler statement.

If you absolutely have to then keep in mind that the VB.NET compiler auto-generates a backing store field for the event with the same name as the event with "Event" appended. Which makes this code work:

    Dim Obj = New SimpleClass
AddHandler Obj.SimpleEvent, Sub()
MsgBox("Hi !")
End Sub

Dim fi = GetType(SimpleClass).GetField("SimpleEventEvent", BindingFlags.NonPublic Or BindingFlags.Instance)
fi.SetValue(Obj, Nothing)

Obj.SimpleMethod() '' No message box

I'll reiterate that you should not do this.

How would it be possible to remove all event handlers of the 'Click' event of a 'Button'?

You can't, basically - at least not without reflection and a lot of grubbiness.

Events are strictly "subscribe, unsubscribe" - you can't unsubscribe someone else's handler, any more than you can change someone else's reference to an object.

remove all EventHandlers of a specific Control

According to this,
for cancelling all Click Events of panel1 do this:

FieldInfo f1 = typeof(Control).GetField("EventClick", BindingFlags.Static| BindingFlags.NonPublic);
object obj = f1.GetValue(panel1);
PropertyInfo pi = panel1.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)pi.GetValue(panel1, null);
list.RemoveHandler(obj, list[obj]);

And for cancelling other events of panel1 change EventClick to event name that you want to remove.

One can get all event names using this code:

EventInfo[] info = type.GetEvents();
for (int i = 0; i < info.Length; i++)
{
Console.WriteLine(info[i].Name + "\n");
}

Javascript/DOM: How to remove all event listeners of a DOM object?

I am not sure what you mean with remove all events. Remove all handlers for a specific type of event or all event handlers for one type?

Remove all event handlers

If you want to remove all event handlers (of any type), you could clone the element and replace it with its clone:

var clone = element.cloneNode(true);

Note: This will preserve attributes and children, but it will not preserve any changes to DOM properties.



Remove "anonymous" event handlers of specific type

The other way is to use removeEventListener() but I guess you already tried this and it didn't work. Here is the catch:

Calling addEventListener to an anonymous function creates a new listener each time. Calling removeEventListener to an anonymous function has no effect. An anonymous function creates a unique object each time it is called, it is not a reference to an existing object though it may call one. When adding an event listener in this manner be sure it is added only once, it is permanent (cannot be removed) until the object it was added to, is destroyed.

You are essentially passing an anonymous function to addEventListener as eventReturner returns a function.

You have two possibilities to solve this:

  1. Don't use a function that returns a function. Use the function directly:

     function handler() {
    dosomething();
    }

    div.addEventListener('click',handler,false);
  2. Create a wrapper for addEventListener that stores a reference to the returned function and create some weird removeAllEvents function:

     var _eventHandlers = {}; // somewhere global

    const addListener = (node, event, handler, capture = false) => {
    if (!(event in _eventHandlers)) {
    _eventHandlers[event] = []
    }
    // here we track the events and their nodes (note that we cannot
    // use node as Object keys, as they'd get coerced into a string
    _eventHandlers[event].push({ node: node, handler: handler, capture: capture })
    node.addEventListener(event, handler, capture)
    }

    const removeAllListeners = (targetNode, event) => {
    // remove listeners from the matching nodes
    _eventHandlers[event]
    .filter(({ node }) => node === targetNode)
    .forEach(({ node, handler, capture }) => node.removeEventListener(event, handler, capture))

    // update _eventHandlers global
    _eventHandlers[event] = _eventHandlers[event].filter(
    ({ node }) => node !== targetNode,
    )
    }

And then you could use it with:

    addListener(div, 'click', eventReturner(), false)
// and later
removeAllListeners(div, 'click')

DEMO

Note: If your code runs for a long time and you are creating and removing a lot of elements, you would have to make sure to remove the elements contained in _eventHandlers when you destroy them.

Remove All Event Listeners of Specific Type

That is not possible without intercepting addEventListener calls and keep track of the listeners or use a library that allows such features unfortunately. It would have been if the listeners collection was accessible but the feature wasn't implemented.

The closest thing you can do is to remove all listeners by cloning the element, which will not clone the listeners collection.

Note: This will also remove listeners on element's children.

var el = document.getElementById('el-id'),
elClone = el.cloneNode(true);

el.parentNode.replaceChild(elClone, el);


Related Topics



Leave a reply



Submit