473,388 Members | 1,026 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,388 software developers and data experts.

Event with multiple subscribers. Cancel invocation of other handlers.


Hi all,

If an event has multiple subscribers, is it possible to cancel the
invocation of event handlers from an event handler?

Or to be more specific:

I'm subscribing to the ColumnChanging event of a datatable, from two
seperate classes. I wish to do some data validating. Due to the nature of
the data validation being done, I seperated this code in two classes.

When the value changes, as expected, both event handlers are being invoked.
However, if the first validation rejects the data, the second handler really
shouldn't be invoked anymore. I would like to cancel the remaining handler
invocations.

Is this (easily) possible?

Thanks.

Jan 15 '06 #1
6 4928
Peter,

It's not easy, but it is possible.

What you want to do is derive your EventArgs class from CancelEventArgs.
This exposes a Cancel property which can be set to true to indicate that the
action should be cancelled.

Then, what you have to do is get the invocation list for your field
where the event is stored. You can do this by calling GetInvocationList.

Then, you would loop through that list, calling the delegate. If the
Cancel property is set to true, then you stop invocation.

Of course, this means your event handlers have to set the Cancel
property to indicate that there is a problem, or the validation failed.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter M." <Pe*****************@chello.nl> wrote in message
news:20**************************@news.chello.nl.. .

Hi all,

If an event has multiple subscribers, is it possible to cancel the
invocation of event handlers from an event handler?

Or to be more specific:

I'm subscribing to the ColumnChanging event of a datatable, from two
seperate classes. I wish to do some data validating. Due to the nature of
the data validation being done, I seperated this code in two classes.

When the value changes, as expected, both event handlers are being
invoked. However, if the first validation rejects the data, the second
handler really shouldn't be invoked anymore. I would like to cancel the
remaining handler invocations.

Is this (easily) possible?

Thanks.

Jan 15 '06 #2

Thanks for your answer. Your answer pretty much confirms what I was afraid
of, that an easy clean solution is not readily availabe.

I think I will give my design some more thought and put validation code in
one place.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> schreef
in bericht news:%2****************@TK2MSFTNGP09.phx.gbl...
Peter,

It's not easy, but it is possible.

What you want to do is derive your EventArgs class from
CancelEventArgs. This exposes a Cancel property which can be set to true
to indicate that the action should be cancelled.

Then, what you have to do is get the invocation list for your field
where the event is stored. You can do this by calling GetInvocationList.

Then, you would loop through that list, calling the delegate. If the
Cancel property is set to true, then you stop invocation.

Of course, this means your event handlers have to set the Cancel
property to indicate that there is a problem, or the validation failed.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter M." <Pe*****************@chello.nl> wrote in message
news:20**************************@news.chello.nl.. .

Hi all,

If an event has multiple subscribers, is it possible to cancel the
invocation of event handlers from an event handler?

Or to be more specific:

I'm subscribing to the ColumnChanging event of a datatable, from two
seperate classes. I wish to do some data validating. Due to the nature of
the data validation being done, I seperated this code in two classes.

When the value changes, as expected, both event handlers are being
invoked. However, if the first validation rejects the data, the second
handler really shouldn't be invoked anymore. I would like to cancel the
remaining handler invocations.

Is this (easily) possible?

Thanks.


Jan 15 '06 #3
To be fair, this adds about 2 lines to the code that fires the event - one
"foreach", and one "if"... and could probably be wrapped into a helper
function for even more re-use in about 2 minutes... to me that qualifies as
easy, *reasonably* clean, and readily available.

Marc

"Peter M." <Pe*****************@chello.nl> wrote in message
news:90**************************@news.chello.nl.. .

Thanks for your answer. Your answer pretty much confirms what I was afraid
of, that an easy clean solution is not readily availabe.

I think I will give my design some more thought and put validation code in
one place.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> schreef
in bericht news:%2****************@TK2MSFTNGP09.phx.gbl...
Peter,

It's not easy, but it is possible.

What you want to do is derive your EventArgs class from
CancelEventArgs. This exposes a Cancel property which can be set to true
to indicate that the action should be cancelled.

Then, what you have to do is get the invocation list for your field
where the event is stored. You can do this by calling GetInvocationList.

Then, you would loop through that list, calling the delegate. If the
Cancel property is set to true, then you stop invocation.

Of course, this means your event handlers have to set the Cancel
property to indicate that there is a problem, or the validation failed.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter M." <Pe*****************@chello.nl> wrote in message
news:20**************************@news.chello.nl.. .

Hi all,

If an event has multiple subscribers, is it possible to cancel the
invocation of event handlers from an event handler?

Or to be more specific:

I'm subscribing to the ColumnChanging event of a datatable, from two
seperate classes. I wish to do some data validating. Due to the nature
of the data validation being done, I seperated this code in two classes.

When the value changes, as expected, both event handlers are being
invoked. However, if the first validation rejects the data, the second
handler really shouldn't be invoked anymore. I would like to cancel the
remaining handler invocations.

Is this (easily) possible?

Thanks.



Jan 15 '06 #4
Apols - I misread the event details; since the datatable's event isn't owned
by your code, this would indeed be quite tricky. However, you could (maybe)
subscribe with a forwarding mechanism? i.e. you have one instance (of a
proxy class) subscribe to the datatable's events, which then enumerates
through it's own subscribers (exposing the original args as a param of the
new CancelEventArgs based args), stopping if/when necessary

Perhaps...

Marc

"Marc Gravell" <mg******@rm.com> wrote in message
news:OO**************@tk2msftngp13.phx.gbl...
To be fair, this adds about 2 lines to the code that fires the event - one
"foreach", and one "if"... and could probably be wrapped into a helper
function for even more re-use in about 2 minutes... to me that qualifies
as easy, *reasonably* clean, and readily available.

Marc

"Peter M." <Pe*****************@chello.nl> wrote in message
news:90**************************@news.chello.nl.. .

Thanks for your answer. Your answer pretty much confirms what I was
afraid of, that an easy clean solution is not readily availabe.

I think I will give my design some more thought and put validation code
in one place.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com>
schreef in bericht news:%2****************@TK2MSFTNGP09.phx.gbl...
Peter,

It's not easy, but it is possible.

What you want to do is derive your EventArgs class from
CancelEventArgs. This exposes a Cancel property which can be set to true
to indicate that the action should be cancelled.

Then, what you have to do is get the invocation list for your field
where the event is stored. You can do this by calling
GetInvocationList.

Then, you would loop through that list, calling the delegate. If the
Cancel property is set to true, then you stop invocation.

Of course, this means your event handlers have to set the Cancel
property to indicate that there is a problem, or the validation failed.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter M." <Pe*****************@chello.nl> wrote in message
news:20**************************@news.chello.nl.. .

Hi all,

If an event has multiple subscribers, is it possible to cancel the
invocation of event handlers from an event handler?

Or to be more specific:

I'm subscribing to the ColumnChanging event of a datatable, from two
seperate classes. I wish to do some data validating. Due to the nature
of the data validation being done, I seperated this code in two
classes.

When the value changes, as expected, both event handlers are being
invoked. However, if the first validation rejects the data, the second
handler really shouldn't be invoked anymore. I would like to cancel the
remaining handler invocations.

Is this (easily) possible?

Thanks.




Jan 15 '06 #5
To show what I meant: here, EventProxy will only work with EventArgs type
args, and Handler will only match the standard event-handler signature, but
this code suffices to short-circuit the invocation of events where we don't
own the original code (i.e. we can't change it to a simple CancelEventArgs
type implementation). In the demo, note that if you press a, only "1" & "2"
are fired; if you use Ctrl, only "1" is fired, else they all do.

This might save you from refactoring? Of course, you still need to indicate
to the original args what happened...

Marc

public static void Main() {
using (Form form = new Form()) {
TextBox tb = new TextBox();
form.Controls.Add(tb);
EventProxy<KeyEventArgs> ep = new
EventProxy<KeyEventArgs>();
ep.Event += Handler1;
ep.Event += Handler2;
ep.Event += Handler3;
tb.KeyDown += ep.Handler;
form.ShowDialog();
}
}

static void Handler1(object sender,
EventProxyEventArgs<KeyEventArgs> e) {
System.Diagnostics.Debug.WriteLine("Handler1");
if (e.InnerEventArgs.Control)
e.Cancel = true;
}
static void Handler2(object sender,
EventProxyEventArgs<KeyEventArgs> e) {
System.Diagnostics.Debug.WriteLine("Handler2");
if (e.InnerEventArgs.KeyData == Keys.A)
e.Cancel = true;
}
static void Handler3(object sender,
EventProxyEventArgs<KeyEventArgs> e) {
System.Diagnostics.Debug.WriteLine("Handler3");
}
}

public class EventProxyEventArgs<T> : CancelEventArgs where T :
EventArgs {
public readonly T InnerEventArgs; // cheap for demo
public EventProxyEventArgs(T innerEventArgs) {
InnerEventArgs = innerEventArgs;
}
}
public class EventProxy<T> where T : EventArgs {
public event EventHandler<EventProxyEventArgs<T>> Event;
public void Handler(object sender, T eventArgs) {
if (Event != null) {
EventProxyEventArgs<T> args = new
EventProxyEventArgs<T>(eventArgs);
foreach(EventHandler<EventProxyEventArgs<T>> subscriber in
Event.GetInvocationList()) {
subscriber(sender, args); // using original sender;
could use "this" and pass original in args
if (args.Cancel) break;
}
}

}
}
Jan 15 '06 #6
Marc,

Thanks for your answer.

I 'll try your code and see if this could be of any help.

I appreciate the effort.

peter.
"Marc Gravell" <mg******@rm.com> schreef in bericht
news:eh**************@TK2MSFTNGP14.phx.gbl...
To show what I meant: here, EventProxy will only work with EventArgs type
args, and Handler will only match the standard event-handler signature,
but this code suffices to short-circuit the invocation of events where we
don't own the original code (i.e. we can't change it to a simple
CancelEventArgs type implementation). In the demo, note that if you press
a, only "1" & "2" are fired; if you use Ctrl, only "1" is fired, else they
all do.

This might save you from refactoring? Of course, you still need to
indicate to the original args what happened...

Marc

public static void Main() {
using (Form form = new Form()) {
TextBox tb = new TextBox();
form.Controls.Add(tb);
EventProxy<KeyEventArgs> ep = new
EventProxy<KeyEventArgs>();
ep.Event += Handler1;
ep.Event += Handler2;
ep.Event += Handler3;
tb.KeyDown += ep.Handler;
form.ShowDialog();
}
}

static void Handler1(object sender,
EventProxyEventArgs<KeyEventArgs> e) {
System.Diagnostics.Debug.WriteLine("Handler1");
if (e.InnerEventArgs.Control)
e.Cancel = true;
}
static void Handler2(object sender,
EventProxyEventArgs<KeyEventArgs> e) {
System.Diagnostics.Debug.WriteLine("Handler2");
if (e.InnerEventArgs.KeyData == Keys.A)
e.Cancel = true;
}
static void Handler3(object sender,
EventProxyEventArgs<KeyEventArgs> e) {
System.Diagnostics.Debug.WriteLine("Handler3");
}
}

public class EventProxyEventArgs<T> : CancelEventArgs where T :
EventArgs {
public readonly T InnerEventArgs; // cheap for demo
public EventProxyEventArgs(T innerEventArgs) {
InnerEventArgs = innerEventArgs;
}
}
public class EventProxy<T> where T : EventArgs {
public event EventHandler<EventProxyEventArgs<T>> Event;
public void Handler(object sender, T eventArgs) {
if (Event != null) {
EventProxyEventArgs<T> args = new
EventProxyEventArgs<T>(eventArgs);
foreach(EventHandler<EventProxyEventArgs<T>> subscriber in
Event.GetInvocationList()) {
subscriber(sender, args); // using original sender;
could use "this" and pass original in args
if (args.Cancel) break;
}
}

}
}

Jan 17 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Pavils Jurjans | last post by:
Hello, I wanted to propose a small class that would help to overcome the feature that's missing in MSIE. I'd like to get some feedback from people and, perhaps, improvements in code/other ideas:...
1
by: Fei Li | last post by:
I do not know if event handlers are called by the sequence of the subsription sequence.
18
by: bhavin | last post by:
Hi, Can someone point me to some good best practices kind of documentation on use of events compared to method overriding. Ex. In Windows Forms when should i have an event handler for Paint, and...
13
by: Charles Law | last post by:
Mr "yEaH rIgHt" posted the following link about a week ago in answer to my question about removing event handlers. > http://www.vbinfozine.com/t_bindevt.shtml Following on from that post, the...
3
by: Andrew Ducker | last post by:
I have a class with a DataTable built into it. Various places subscribe to the DataTable.RowChanging event. I want to grab a list of all the subscribers. Normally I'd use GetInvocationList,...
0
by: Vasiliy | last post by:
Hi all! I'm developing an application to manage word templates and documents. Documents are stored in database, so when user wants to edit a document i make a local copy of this document and then...
3
by: Smithers | last post by:
In consideration of the brief sample code at the following link... http://msdn2.microsoft.com/en-us/library/system.componentmodel.canceleventargs.cancel.aspx .... when we set e.Cancel = true,...
31
by: Scott M. | last post by:
Am I correct in thinking that because C# doesn't have the "Handles" keyword that VB .NET does, we have to register event delegates manually in C#, whereas in VB .NET using "Handles" takes care of...
4
by: =?Utf-8?B?TmF2YW5lZXRoLksuTg==?= | last post by:
Hi all, Recently I found an interesting question on C# forums about clearing event handlers of an event. I tried to give it a solution, but failed. I am interested to know how you guys take...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.