PDA

View Full Version : [CLOSED] Delete / Remove directevent handler in code behind



jwf
Jan 29, 2013, 9:17 PM
I have a grid panel which defines a DirectEvent handler for the ItemDblClick event:



<DirectEvents>
<ItemDblClick OnEvent="SelectEvent">
<EventMask ShowMask="true" Msg="Loading Dialog, Please Wait..." />
</ItemDblClick>
</DirectEvents>

When a particular class of user visits the page, I need to disable this event from code-behind.

I have this code in the OnInit event of my page code-behind:



grid.DirectEvents.ItemDblClick.Event -= SelectEvent;


However the event still fires on the client and the loading mask is displayed; all this does is stop the event handler from executing. How do I completely remove this event, so that nothing occurs on either client or server?

Thanks,

jwf

jwf
Jan 29, 2013, 9:34 PM
Well I found a partial solution - this works:


grid.DirectEvents.ItemDblClick.EventMask.ShowMask = false;

But I still feel like there must be a better way to tell the event not to be handled, rather than to hide the evidence of being handled, so I'll leave this thread open and see what advice you guys can come up with.

Baidaly
Jan 29, 2013, 10:29 PM
Hello!

I think it's better to use Before property to make condition of calling DirectEvent.

Actually,
ShowMask = false doesn't prevent execution of DirectEvent it just removes Loading Mask but DirectEvent is still calling.

jwf
Jan 29, 2013, 11:06 PM
Thanks Baidaly, that worked fine. Here's what I ended up doing for anyone reading the thread at a later date:


grid.DirectEvents.ItemDblClick.Before = "return false;";

You can close the thread.

Daniil
Jan 30, 2013, 4:48 AM
Hi everybody,

Yes, returning false from a Before handler (or from the same client listener) is the best solution to manage DirectEvents.




I have this code in the OnInit event of my page code-behind:



grid.DirectEvents.ItemDblClick.Event -= SelectEvent;


However the event still fires on the client and the loading mask is displayed; all this does is stop the event handler from executing. How do I completely remove this event, so that nothing occurs on either client or server?

I think calling "-=" in OnInit event should work. At least, it works in the example below.

(Please note that it won't work during a DirectEvent).

Example

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void Page_Init(object sender, EventArgs e)
{
this.Button1.DirectEvents.Click.Event -= TestDirectEventHandler;
}

protected void TestDirectEventHandler(object sender, DirectEventArgs e)
{
X.Msg.Alert("DirectEvent", "Hello from Server!").Show();
}
</script>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Ext.NET v2 Example</title>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />

<ext:Button ID="Button1" runat="server" Text="Test">
<DirectEvents>
<Click OnEvent="TestDirectEventHandler" />
</DirectEvents>
</ext:Button>
</form>
</body>
</html>

michaeld
Oct 02, 2013, 12:44 PM
So, here's what I've found. There are two cases one might wish to disable a DirectEvent. One is in the case of OnInit; the other is in a DirectEvent.

In the case of an OnInit, I frequently will initialize a button (or other control) with both a Listener and a DirectEvent in the ascx file for the same event. Then during Initialization set the Clicks Listener's Handler to null or -= the Click DirectEvent's Event.

In the case of a DirectEvent, I need to be able to turn off Events and Listeners on the same or other controls.


I think calling "-=" in OnInit event should work.

I've found this however does work in some cases, but not all. I haven't worked out why that is yet. However, I created a sample below that reliably does not.

This works in the OnInit though.



grid.DirectEvents.ItemDblClick.Before = "return false;";

However, all 3 scenarios fail in a DirectEvent. With Listeners, you can't set the Click Handler to NULL. You can't set Events -= or set it's Before. No code renders back.

In this sample of code, I create a Button with both DirectEvent & Listener for Click. During OnInit I try to disable the Event without effect just to show you. I remark out a piece of code that sets the Listeners handler to null but that works so it's insignificant here.

If you run the code, after the first time you click the button, it displays a standard javascript alert from the listener, then a Ext.Net Alert from the Direct Event. After the DirectEvent I'd hoped to turn it off so nothing happens if you click the button again, but both occur still.



<%@ Page Language="C#" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>


<script runat="server">
protected void Page_Load( object sender, EventArgs e ) {
if( X.IsAjaxRequest )
return;
Btn.DirectEvents.Click.Event -= OnClick; // This should have turned off the DirectEvent; it does not.
//Btn.Listeners.Click.Handler = null; // When remark is removed, this scenario at least works
}
public void OnClick( object sender, DirectEventArgs e ) {
Btn.DirectEvents.Click.Before = "return false;"; // This does nothing
Btn.Listeners.Click.Handler = null;// This does nothing
X.MessageBox.Alert( "Test", "Test" ).Show();
}
</script>


<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<title>Test33</title>
</head>
<body>
<form id="Form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server" ViewStateMode="Enabled" ScriptMode="Debug" SourceFormatting="true" />
<ext:Viewport ID="vp" runat="server">
<Items>
<ext:Button ID="Btn" runat="server" Text="Test">
<Listeners>
<Click Handler="alert('test');" />
</Listeners>
<DirectEvents>
<Click OnEvent="OnClick"></Click>
</DirectEvents>
</ext:Button>
</Items>
<Items>


</Items>
</ext:Viewport>


</form>
</body>
</html>



Ideally, I don't know what you guys think it should be doing here, but it REALLY would be nice if you guys added a method to disable/enable events to the trunk [A FEATURE REQUEST].

I tried adding this to the ObservableDirectEvent class just for testing, and yeah, it works for OnInit, but I think you guys can do better; one that should work in DirectEvents too.


public virtual void DisableEvent()
{
var before = this.Before;
if( !string.IsNullOrEmpty( before ) )
this.Before = "return false;;" + before;
else
this.Before = "return false;;";
}


public virtual void EnableEvent()
{
var before = this.Before;
if( !string.IsNullOrEmpty( before ) && before.StartsWith( "return false;;" ) )
this.Before = before.Substring( 14 );
}
}


Please help.

Daniil
Oct 02, 2013, 3:46 PM
Hi @michaeld,

Let's consider this piece of code.

protected void Page_Load( object sender, EventArgs e ) {
if ( X.IsAjaxRequest )
return;

Btn.DirectEvents.Click.Event -= OnClick; // This should have turned off the DirectEvent; it does not.
}

X.IsAjaxRequest is true during a DirectEvent. So, the "-=" thing is just not executed.

Though, it is not so important. More important is the fact that the Button is already rendered including JavaScript DirectEvent part. So, even if you detach a server handler, it doesn't remove a JavaScript part of DirectEvent.

As for these things:

Btn.DirectEvents.Click.Before = "return false;"; // This does nothing
Btn.Listeners.Click.Handler = null;// This does nothing

It doesn't affect if a component is already rendered to client. To get those changes affected you could re-render a component. But I don't think it is a good solution. I would suggest you something like this.

There is a problem though. For some reason DirectEvent are not suspended by a suspendEvent call. We are investigating.

Example

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void Button1_Click(object sender, DirectEventArgs e)
{
X.Msg.Alert("Button_Click", "Click DirectEvent").Show();
}

protected void Suspend(object sender, DirectEventArgs e)
{
this.Button1.Call("suspendEvent", "click");
}

protected void Resume(object sender, DirectEventArgs e)
{
this.Button1.Call("resumeEvent", "click");
}
</script>

<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET v2 Example</title>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />

<ext:Button ID="Button1" runat="server" Text="Test">
<Listeners>
<Click Handler="alert('Click Listener')" />
</Listeners>
<DirectEvents>
<Click OnEvent="Button1_Click" />
</DirectEvents>
</ext:Button>

<ext:Button runat="server" Text="Suspend click event via JavaScript">
<Listeners>
<Click Handler="App.Button1.suspendEvent('click');" />
</Listeners>
</ext:Button>

<ext:Button runat="server" Text="Resume click event via JavaScript">
<Listeners>
<Click Handler="App.Button1.resumeEvent('click');" />
</Listeners>
</ext:Button>

<ext:Button runat="server" Text="Suspend click event via code behind" OnDirectClick="Suspend" />

<ext:Button runat="server" Text="Resume click event via code behind" OnDirectClick="Resume" />
</form>
</body>
</html>

michaeld
Oct 04, 2013, 10:33 AM
I guess I'm hoping for a slightly more of an ext.net library solution.

It seems to me with listeners, the initialization render creates the listeners in the rendered initialization json. It just seems to me that if dom events are just variables that when fired traverse through the list of targets, why can't they be removed as well as added as a javascript call as simply as setValue() or any other function?

With DirectEvents that same model of working may not be compatible, but prepending or replacing the before with "return false;" seems viable as something that can be rendered into the returning stream. eg X.Script(...)

I may be totally be out of sync with implementation, but does this theory stand to reason at all?
And if not, even your solution seems to suggest an extnet api to disable specific events could be integrated as a callable function in extnet library in a direct event.


Thoughts?

Daniil
Oct 04, 2013, 2:21 PM
It might be possible


It seems to me with listeners, the initialization render creates the listeners in the rendered initialization json. It just seems to me that if dom events are just variables that when fired traverse through the list of targets, why can't they be removed as well as added as a javascript call as simply as setValue() or any other function?

There is a removeListener method.
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.util.Observable-method-removeListener

There is a server side counterpart as well.


With DirectEvents that same model of working may not be compatible, but prepending or replacing the before with "return false;" seems viable as something that can be rendered into the returning stream. eg X.Script(...)

We will think about a possibility remove a DirectEvent. Thank you for the suggestion.



And if not, even your solution seems to suggest an extnet api to disable specific events could be integrated as a callable function in extnet library in a direct event.


Do you mean server SuspendEvent and ResumeEvent methods? Yes, we are going to add it.

michaeld
Oct 06, 2013, 3:43 AM
There is a removeListener method.
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.util.Observable-method-removeListener
There is a server side counterpart as well.

I'll give it a shot.



We will think about a possibility remove a DirectEvent. Thank you for the suggestion.


Yeah, this ones a big one. See my recent post here for another example why it's critical.
http://forums.ext.net/showthread.php?26723-Feature-Request-Visible-false-DirectEvent-Visible-true-X-Render-ideas

Also, I've tested setting Before="return false;" in a DirectEvent and it does nothing. I'm also observing unreliable results doing the same thing in the Page_Load which I'm investigating and am not ready to confirm yet.

michaeld
Oct 06, 2013, 12:11 PM
I understand a bit more why the sample code I gave you before didn't work the way I expected, but I am still having a case that I cannot produce in a sample where -= doesn't work, so I've resorted to setting Before="return false;". However, I found another situation where Confirmation will still show even though.



<ext:Button ID="Btn" runat="server" Text="Test">
<Listeners>
<Click Handler="alert('test');" />
</Listeners>
<DirectEvents>
<Click OnEvent="OnClick" Before="return false;">
<Confirmation ConfirmRequest="true" Message="Are you sure?" Title="Confirm" />
</Click>
</DirectEvents>
</ext:Button>



This will deactivate the OnEvent from ever being triggered, but not the ConfirmRequest. It's kind of frustrating that presently if I want to turn off the click event in the server-side, I have to deactivate both the Click Event Before="return false" and set the Confirmation.ConfirmRequest="false" just to prevent confusion to the user.

In the meantime, till you guys have a more robust situation, the following extension method allows me (or anyone) to reliably Disable any event Event as long as its a part of the Page_Load(). I'll have to wait till you have a solution on the DirectEvent side.


public static void DisableEvent( this ComponentDirectEvent evt ) {
var before = evt.Before;
if( !string.IsNullOrEmpty( before ) )
evt.Before = "return false;;" + before;// 2 semicolons are used to indicate intensional override
else
evt.Before = "return false;;";
if( evt.Confirmation.ConfirmRequest )
evt.Confirmation.ConfirmRequest = false;
}


public static void EnableEvent( this ComponentDirectEvent evt ) {
var before = evt.Before;
if( !string.IsNullOrEmpty( before ) && before.StartsWith( "return false;;" ) )
evt.Before = before.Substring( 14 );
if( evt.Confirmation.ConfirmRequest == false && !string.IsNullOrEmpty( evt.Confirmation.Message ) )
evt.Confirmation.ConfirmRequest = true;
}

Daniil
Oct 07, 2013, 5:23 AM
Generally speaking, the "-=" thing detaches the server side handler only. It doesn't do anything on client.

Something has been committed to the SVN trunk.

1. The suspendEvent/resumeEvent methods work for a DirectEvent. So, this examples is fully functioning.

Example SuspendEvent/ResumeEvent

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void Button1_Click(object sender, DirectEventArgs e)
{
X.Msg.Alert("Button_Click", "Click DirectEvent").Show();
}

protected void Suspend(object sender, DirectEventArgs e)
{
this.Button1.SuspendEvent("click");
}

protected void Resume(object sender, DirectEventArgs e)
{
this.Button1.ResumeEvent("click");
}
</script>

<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET v2 Example</title>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />

<ext:Button ID="Button1" runat="server" Text="Test">
<Listeners>
<Click Handler="alert('Click Listener')" />
</Listeners>
<DirectEvents>
<Click OnEvent="Button1_Click" />
</DirectEvents>
</ext:Button>

<ext:Button runat="server" Text="Suspend click event via JavaScript">
<Listeners>
<Click Handler="App.Button1.suspendEvent('click');" />
</Listeners>
</ext:Button>

<ext:Button runat="server" Text="Resume click event via JavaScript">
<Listeners>
<Click Handler="App.Button1.resumeEvent('click');" />
</Listeners>
</ext:Button>

<ext:Button runat="server" Text="Suspend click event via code behind" OnDirectClick="Suspend" />

<ext:Button runat="server" Text="Resume click event via code behind" OnDirectClick="Resume" />
</form>
</body>
</html>

2. The new RemoveDirectListener has been appeared.

Example RemoveDirectListener

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void Button1_Click(object sender, DirectEventArgs e)
{
X.Msg.Alert("Button_Click", "Click DirectEvent").Show();
}

protected void Remove(object sender, DirectEventArgs e)
{
this.Button1.RemoveDirectListener("click");
}
</script>

<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET v2 Example</title>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />

<ext:Button ID="Button1" runat="server" Text="Test">
<DirectEvents>
<Click OnEvent="Button1_Click" />
</DirectEvents>
</ext:Button>

<ext:Button runat="server" Text="Remove DirectEvent via JavaScript">
<Listeners>
<Click Handler="App.Button1.removeDirectListener('click');" />
</Listeners>
</ext:Button>

<ext:Button runat="server" Text="Remove DirectEvent via code behind" OnDirectClick="Remove" />
</form>
</body>
</html>


Also, I've tested setting Before="return false;" in a DirectEvent and it does nothing.

Also I would like to demonstrate the following technique. It might be helpful in some scenarios.

Examples DirectEvent's Before

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void Button1_Click(object sender, DirectEventArgs e)
{
X.Msg.Alert("Button_Click", "Click DirectEvent").Show();
}

protected void Lock(object sender, DirectEventArgs e)
{
this.Button1.Set("clickDirectEventlock", true);
}

protected void Unlock(object sender, DirectEventArgs e)
{
this.Button1.Set("clickDirectEventlock", false);
}
</script>

<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET v2 Example</title>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />

<ext:Button ID="Button1" runat="server" Text="Test">
<DirectEvents>
<Click OnEvent="Button1_Click" Before="return !this.clickDirectEventlock;" />
</DirectEvents>
</ext:Button>

<ext:Button runat="server" Text="Lock DirectEvent via JavaScript">
<Listeners>
<Click Handler="App.Button1.clickDirectEventlock = true;" />
</Listeners>
</ext:Button>

<ext:Button runat="server" Text="Unlock DirectEvent via JavaScript">
<Listeners>
<Click Handler="App.Button1.clickDirectEventlock = false;" />
</Listeners>
</ext:Button>

<ext:Button runat="server" Text="Lock DirectEvent via code behind" OnDirectClick="Lock" />

<ext:Button runat="server" Text="Unlock DirectEvent via code behind" OnDirectClick="Unlock" />
</form>
</body>
</html>

michaeld
Oct 09, 2013, 6:48 AM
Okay, great. RemoveDirectListener allows me to remove a DirectEvent on postback. How to I restore it?

michaeld
Oct 09, 2013, 7:03 AM
I've also thought about this a little bit more from your .net programmer's perspective? Wouldn't it be wiser to add this method to the actual ObservableDirectEvent? It would be easier if we weren't expected to remember the extjs names that match the Events except on the client-side.

So I'm thinking you already have the ConfigOption name available so it should be very easy to call something like, ...



Button1.DirectEvents.Click.RemoveDirectListener();
Button1.DirectEvents.Click.SuspendEvent();
Button1.DirectEvents.Click.ResumeEvent();


This way you have both the parent and the actual extjs listener name available and the programmer is ensured to reference the correct extjs listener without having to look it up. I realize this may be a little more work, but it seems like the right way to do it. Just a thought.

Both options might be practical and I realize SuspendEvent(name) and ResumeEvent(name) might be appropriate to have in both places as well.

And yeah, it would follow that the same should work for Listeners too.


Button1.Listeners.Click.Remove();
Button1.Listeners.Click.SuspendEvent();
Button1.Listeners.Click.ResumeEvent();


Curious though. Does SuspendEvent suspend both the DirectEvent and the Listener event with the same name?

Daniil
Jan 14, 2014, 4:24 AM
We apologize for such the delay in responding.


Okay, great. RemoveDirectListener allows me to remove a DirectEvent on postback. How to I restore it?

I don't see a simple way. If you need to remove and have a possibility to restore, it is better to operate with lock/unlock.


I've also thought about this a little bit more from your .net programmer's perspective? Wouldn't it be wiser to add this method to the actual ObservableDirectEvent? It would be easier if we weren't expected to remember the extjs names that match the Events except on the client-side.

So I'm thinking you already have the ConfigOption name available so it should be very easy to call something like, ...



Button1.DirectEvents.Click.RemoveDirectListener();
Button1.DirectEvents.Click.SuspendEvent();
Button1.DirectEvents.Click.ResumeEvent();


This way you have both the parent and the actual extjs listener name available and the programmer is ensured to reference the correct extjs listener without having to look it up. I realize this may be a little more work, but it seems like the right way to do it. Just a thought.

Both options might be practical and I realize SuspendEvent(name) and ResumeEvent(name) might be appropriate to have in both places as well.

And yeah, it would follow that the same should work for Listeners too.


Button1.Listeners.Click.Remove();
Button1.Listeners.Click.SuspendEvent();
Button1.Listeners.Click.ResumeEvent();


Well, DirectEvents's names always match the client side Listeners'. Though, your suggestion is very good in API terms. Unfortunately, it is not that simple to implement and I am not sure it is worth enough.



Curious though. Does SuspendEvent suspend both the DirectEvent and the Listener event with the same name?

Yes, it suspends both of them.