Determine the current event

  • Thread starter Thread starter Christopher W. Douglas
  • Start date Start date
C

Christopher W. Douglas

I am writing a VB.NET application in Visual Studio 2003. I have written a
method that handles several events, such as closing a form and changing the
visible status of a form. I have some code that applies to all these
events, but I need to have specific code execute when the form closes. The
properties for this method are sender (the originator) and e (event
arguments). I know how to get typeof (sender) to determine what form or
control the event originated from, but how do I determine which event was
fired? I would think that eventargs contains the type of event that fired,
but I could not find anything in MSDN detailing this. Thanks for your help.
 
You need to getType of 'e' to determine what type it is and then take it
from there.

OHM#
I am writing a VB.NET application in Visual Studio 2003. I have
written a method that handles several events, such as closing a form
and changing the visible status of a form. I have some code that
applies to all these events, but I need to have specific code execute
when the form closes. The properties for this method are sender (the
originator) and e (event arguments). I know how to get typeof
(sender) to determine what form or control the event originated from,
but how do I determine which event was fired? I would think that
eventargs contains the type of event that fired, but I could not find
anything in MSDN detailing this. Thanks for your help.

Regards - OHM# (e-mail address removed)
 
Christopher W. Douglas said:
I am writing a VB.NET application in Visual Studio 2003. I have
written a method that handles several events, such as closing a form
and changing the visible status of a form. I have some code that
applies to all these events, but I need to have specific code execute
when the form closes. The properties for this method are sender (the
originator) and e (event arguments). I know how to get typeof
(sender) to determine what form or control the event originated from,
but how do I determine which event was fired? I would think that
eventargs contains the type of event that fired, but I could not find
anything in MSDN detailing this. Thanks for your help.

If you want to handle different events you should write different
procedures. Otherwise it's like pouring two glasses of water together and
trying to find out where each drop came from.
 
You need to getType of 'e' to determine what type it
is and then take it from there.

GetType(e) will return the same thing each time (EventArgs class) because it
is the same method that is handling the different events mentioned.
 
Thinking about it, yes your right! , what would be your answer to the OP
then?

OHM
You need to getType of 'e' to determine what type it
is and then take it from there.

GetType(e) will return the same thing each time (EventArgs class)
because it is the same method that is handling the different events
mentioned.


"One Handed Man [ OHM# ]"
You need to getType of 'e' to determine what type it is and then
take it from there.

OHM#


Regards - OHM# (e-mail address removed)

Regards - OHM# (e-mail address removed)
 
Christopher,

You are correct that the "Sender" argument identifies the form or control
that raised the event. The "e" or EventArgs argument is simply an object
that contains additional arguments specific to that event. As many different
events share the same type of parameters (called its "Signature") you cannot
identifty the actual event being rased from this parameter.

You would be better off having separate event handler methods for each event
and moving the common code into a separate procedure which is called from
each event handler.


For example:
---------------------------------
Private Sub Form_Closing(ByVal sender As Object, ByVal e As CancelEventArgs)
Handles MyBase.Closing

DoCommonStuff()
' Code for closing goes here

End Sub

Private Sub Form_VisibleChanged(ByVal sender As Object, ByVal e As
EventArgs) Handles MyBase.VisibleChanged

DoCommonStuff()
' Code for visible changed goes here

End Sub

Private Sub DoCommonStuff()

' Do stuff common to both events here

End Sub
 
what would be your answer to the OP

My post hasn't seemed to appear yet. Watch this space ;)

One Handed Man said:
Thinking about it, yes your right! , what would be your answer to the OP
then?

OHM
You need to getType of 'e' to determine what type it
is and then take it from there.

GetType(e) will return the same thing each time (EventArgs class)
because it is the same method that is handling the different events
mentioned.


"One Handed Man [ OHM# ]"
You need to getType of 'e' to determine what type it is and then
take it from there.

OHM#

Christopher W. Douglas wrote:
I am writing a VB.NET application in Visual Studio 2003. I have
written a method that handles several events, such as closing a form
and changing the visible status of a form. I have some code that
applies to all these events, but I need to have specific code
execute when the form closes. The properties for this method are
sender (the originator) and e (event arguments). I know how to get
typeof (sender) to determine what form or control the event
originated from, but how do I determine which event was fired? I
would think that eventargs contains the type of event that fired,
but I could not find anything in MSDN detailing this. Thanks for
your help.

Regards - OHM# (e-mail address removed)

Regards - OHM# (e-mail address removed)
 
Hi Armin,
If you want to handle different events you should write different
procedures. Otherwise it's like pouring two glasses of water together and
trying to find out where each drop came from.

That is a very good answer.

Describes exactly the problem in my opinion..

(And I am serious before you don't believe it.)

Cor
 
Good advice CM, I really should have thought more before my posting <slaps
self on head>

Thanks !

OHM
what would be your answer to the OP

My post hasn't seemed to appear yet. Watch this space ;)

"One Handed Man [ OHM# ]"
Thinking about it, yes your right! , what would be your answer to
the OP then?

OHM
You need to getType of 'e' to determine what type it
is and then take it from there.

GetType(e) will return the same thing each time (EventArgs class)
because it is the same method that is handling the different events
mentioned.


"One Handed Man [ OHM# ]"
You need to getType of 'e' to determine what type it is and then
take it from there.

OHM#

Christopher W. Douglas wrote:
I am writing a VB.NET application in Visual Studio 2003. I have
written a method that handles several events, such as closing a
form and changing the visible status of a form. I have some code
that applies to all these events, but I need to have specific code
execute when the form closes. The properties for this method are
sender (the originator) and e (event arguments). I know how to
get typeof (sender) to determine what form or control the event
originated from, but how do I determine which event was fired? I
would think that eventargs contains the type of event that fired,
but I could not find anything in MSDN detailing this. Thanks for
your help.

Regards - OHM# (e-mail address removed)

Regards - OHM# (e-mail address removed)

Regards - OHM# (e-mail address removed)
 
lol. Don't resort to slapping yourself. If I did that, I'd be black and blue
by now!


One Handed Man said:
Good advice CM, I really should have thought more before my posting <slaps
self on head>

Thanks !

OHM
what would be your answer to the OP

My post hasn't seemed to appear yet. Watch this space ;)

"One Handed Man [ OHM# ]"
Thinking about it, yes your right! , what would be your answer to
the OP then?

OHM

Codemonkey wrote:
You need to getType of 'e' to determine what type it
is and then take it from there.

GetType(e) will return the same thing each time (EventArgs class)
because it is the same method that is handling the different events
mentioned.


"One Handed Man [ OHM# ]"
You need to getType of 'e' to determine what type it is and then
take it from there.

OHM#

Christopher W. Douglas wrote:
I am writing a VB.NET application in Visual Studio 2003. I have
written a method that handles several events, such as closing a
form and changing the visible status of a form. I have some code
that applies to all these events, but I need to have specific code
execute when the form closes. The properties for this method are
sender (the originator) and e (event arguments). I know how to
get typeof (sender) to determine what form or control the event
originated from, but how do I determine which event was fired? I
would think that eventargs contains the type of event that fired,
but I could not find anything in MSDN detailing this. Thanks for
your help.

Regards - OHM# (e-mail address removed)

Regards - OHM# (e-mail address removed)

Regards - OHM# (e-mail address removed)
 
CodeMonkey,

Well, that answers my question. I thought I would have to resort to
that, if no one had an answer. But, to rebut Armin's comments, the whole
advantage of .NET is that you can have one handler for multiple events. In
VB6, you would have to write a common function with your code, write an
event handler for EVERY event, and call the common function. I think the
multiple event handler capability is a vast improvement.

That said, it seems to me that you should be able to retrieve from e what
event has occurred! Now, certain events don't have the same signature. In
my case, Form.Closing is different from Form.Closed, so I had to used
Form.Closed because it shares the same signature (object, System.EventArgs)
as Activated and VisibleChanged. Form.Closing has the signature (object,
System.ComponentModel.CancelEventArgs) and thus can't be combined with the
other events.

If what you are saying is true, that the e argument is generic, then I
should be able to string any kind of events together. Since I can't, it
follows that e would have certain properties I can retrieve that describe
the event being handled. Just as a control is not a form (althought one is
derived from the other) but I can use TypeOf (sender) to determine if the
thing causing the event was a menu item, a button, or a form!

It just makes logical sense that you should be able to look at the
properties of an event and determine if it was a button click or a form
being closed that caused the event. I realized logic and Microsoft don't
always go hand in hand, but Visual Studio is nothing if not anal... I can
find the assembly from the e value, I would think I could find the type of
event.

To continue the metaphor, I'm pouring a Black and Tan, so I should still
be able to see the Guinness... :^)
 
Hi Christopher

I am glad they did do it in the way they did it, makes code very transparant
for all kinds of events even if it is multhithreading. Therefore:
I realized logic and Microsoft don't always go hand in hand,

Or did you mena

I realized my logic and Micosoft ..........................

And was it just a typo?

Cor
 
Cor,

No, 'mena' instead of mean and 'Micosoft' instead of Microsoft are
typoes... :^)

Are you then arguing that we should not be able to use typeof(sender) to
determine the originator of the event, either? In a previous application, I
had several ways of calling the same section of code. Depending on where
the event originated (two different menu bars, or a toolbar button), I may
have skipped one section, but always executed the larger section of code.
The code was much more transparent then having a seperate method for every
event, which was the rule in VB6. My current dilemna is that I have the same
originator but am tracing a different kind of event, and I need to write
code appropriately.

I am very happy with the idea of one handler for multiple events, it
makes my previous work possible. HOWEVER, it doesn't make logical sense to
be able to determine the ORIGIN of an error and not be able the determine
the TYPE of error itself...

That is my logical process, which you haven't refuted. While we're
discussing Microsoft and logic, please tell me why a large corporation that
is devoted to building software to make the world run more smoothly seems
incapable of building a help system (online or installed) that anyone can
successfully navigate... :^)
 
Christopher,
I agree with Armin, Codemonkey, Cor & OHM.
Well, that answers my question. I thought I would have to resort to
that, if no one had an answer. But, to rebut Armin's comments, the whole
advantage of .NET is that you can have one handler for multiple events. In
VB6, you would have to write a common function with your code, write an
event handler for EVERY event, and call the common function. I think the
multiple event handler capability is a vast improvement.
Yes it is a vast improvement that I can have a single routine to handle the
SAME event on multiple objects!
That said, it seems to me that you should be able to retrieve from e what
event has occurred!
No the intent is not really to handle different events on the same object,
although this is helpful in many instances!

IMHO The intent is more to allow handling the same event on multiple
objects.

If I have 5 events of the same object, being handled by a common event
handler, that handler SHOULD NOT care why it was called, only that it was
called. If I need to use an If or Select in the handler to decide that I was
called for A or B, then that suggests I need two routines one for A & one
for B. If all of A is performed by B, then B can call A, Or:

You do know using the AddHandler or the Handles syntax you can have the same
event for an object handled multiple times by the same object? So you would
not need to explicitly call A & B above, you could simply have the
Form.Closed event handled by A & B, where as the Button.Click event could be
handled by only A. The danger of this of course is if A has to execute
before B, during the Form.Closed. Of course the event handlers need the same
signatures.
It just makes logical sense that you should be able to look at the
properties of an event and determine if it was a button click or a form
being closed that caused the event. I realized logic and Microsoft don't
always go hand in hand, but Visual Studio is nothing if not anal... I can
find the assembly from the e value, I would think I could find the type of
event.
IMHO: It seems very illogical to want the event type as a parameter to the
event. Yes on the surface it may appear to be a good idea, but if you start
really thinking of how it would be implemented across the breadth of the
Framework, so it works nicely with all events created by any developer, I
see more pain then gain!

The event itself says it was a button click or form being closed, having the
"type" of event as an parameter to the event (either a third parameter or
part of EventArgs) would seem to be extra baggage to me. Plus it may
increase the pressure on the GC, as a new EventArg object may need to be
created for each event raised, most events could not share the
EventArgs.Empty singleton. Or an object would need to be created to indicate
the "type" of event, complicating design. In both cases there would be
pressure on the GC. You could not use an Enum for the "type", as I can add
my own events to a Form or other class, and Enums cannot be extended. A
string would seem to be a good choice, except when you consider that strings
are too easily collided, so you really need a class, as you can use TypeOf
on a class and be certain you are referring to the class you think you are
(as the full name, the name we normally do not see, of the class includes
the assembly & version as well as the namespaces & class name).

Hope this helps
Jay
 
Christopher,
It just makes logical sense that you should be able to look at the
properties of an event and determine if it was a button click or a form
being closed that caused the event. I realized logic and Microsoft don't
always go hand in hand, but Visual Studio is nothing if not anal... I can

If you look at how events are defined in Java, you will find that they don't
include a 'reason' or 'type' of event in the parameters to the event handler
either.

So its not just the OO designers at Microsoft that have this seemingly
illogical view of how events should "logically" work.

Hope this helps
Jay
 
IMHO The intent is more to allow
handling the same event on multiple objects.

I agree, I don't think Microsoft intended the new event handling structure
to allow handling of different events from the same event handler. Instead
it is much more useful for catching the same event from different objects.

For example, consider the performance overhead. If you did have a single
event handler of all events and you did have a method of telling which event
is being handled then you would undoubtedly have to do some processing
(string or type or enum comparison) in order to determine the event. This
would add an additional overhead to handling each event as opposed to having
separate event handlers. Not good when handling performance critical events
such as Paint() etc. You would also end up with a method that is big and
contains code for doing completely separate things - not a good design.
IMHO, a method should have one clearly defined purpose and result.

In my opinion a good use of the new event handling structure is to catch the
same event from multiple objects. For example, say you have a form with 3
text boxes. You could write an event handler like the following to change
the back color of the active textbox to show it as highlighted:

----------------------------

Private Sub GotFocusHandler(sender as object, e as EventArgs) _
Handles Text1.GotFocus, _
Text2.GotFocus, _
Text3.GotFocus

ctype(sender, Control).BackColor = Color.Yellow

End Sub

Private Sub LostFocusHandler(sender as object, e as EventArgs) _
Handles Text1.LostFocus, _
Text2.LostFocus, _
Text3.LostFocus

Ctype(sender, Control).BackColor = SystemColors.Window

End Sub
----------------------------------------------

In the example above, you use the advantage of the new way of handling
events while keeping with good design (atomic methods) and without the
performance bottleneck of determining which event was fired.

Compare this to the way you (Christopher) would like it done:
---------------------------------------------
Private Sub FocusHandler(sender as object, e as EventArgs) _
Handles Text1.LostFocus, _
Text2.LostFocus, _
Text3.LostFocus, _
Text1.GotFocus, _
Text2.GotFocus, _
Text3.GotFocus

If e.Event is Text1.LostFocus or _
e.Event is Text2.LostFocus or _
e.Event is Text3.LostFocus then

Ctype(sender, Control).BackColor = SystemColors.Window

Else

ctype(sender, Control).BackColor = Color.Yellow

End If

End Sub
---------------------------------------------
Although you get away with a single function you have to deal with the
following disadvantages:
1) The performace overhead of determining the event with the IF statement
2) You have a function that is not atomic (it does more than one logical
thing)
3) Debugging may be a bit harder (suppose yor code causes another event to
happen - you have to debug the same function like a recursive call).


I hope this makes things clearer,

Best Regards,

Trev.
 
Jay et al,

Well, it seems the general consensus is that you should not be able to
read the event type from e. I guess you see some aspect here that I don't.
I only asked if you COULD do it, and all I got was why you SHOULDN'T be able
to. I'm not advocating changing anything, I'm just trying to find the best
way to do something. The only solution that seems to be available is to
have separate event functions, which still doesn't sit right with me, but I
appreciate everyone trying to help.

*Takes step back* Now that I have an answer, here is the original
problem. Maybe someone has a much simpler way to solve this. I have an MDI
with several child forms. I want to have hide and unhide capability, like
in Excel and Word. I already have the hide and unhide functionality worked
out, but what I want to do is enable and disable the 'Hide' and 'Unhide'
menu items. I have an event method that handles typical events for a child
form (visiblechanged, activated, closed), where I loop through all the child
forms. If child forms are present and at least one is hidden, I enable the
'Unhide' menu. If at least one is visible, I enable the 'Hide' menu. The
problem is, if you only have one child form and you close it, the 'Unhide'
menu is enabled, because the form still exists when the closed event is
called. All I want is a way to (a) know when the last child window has been
closed and (b) disable the 'Unhide' menu when that happens. Thanks again
for your help.

--
Christopher W. Douglas
SRS Technologies, Inc.
christopher (dot) douglas (at) srs (dot) com
 
Couple of disclaimers - I did not test this on a windows form, so I'm not
sure it would work. Also, I do think you should handle any event that will
require different code in a separate method - That said, there might be a
way to do what you want - I do not advise it, since it makes for pretty
unreadable/unmaintainable code, since it may rely on windows.forms.form
internal implementation.

In other words, the following code is mean as an educational tool, and
probably shouldn't be used in real life. Don't try this at home, and avoid
running with scisors.

here goes nothing:

Module Module1

Sub Main()
Dim c As New c2
c.test()
End Sub

Class c1
Event ev1()
Event ev2()

Sub raise1()
RaiseEvent ev1()
End Sub

Sub raise2()
RaiseEvent ev2()
End Sub
End Class

Class c2
WithEvents c As New c1
Sub handler1() Handles c.ev1, c.ev2
Dim st As New System.Diagnostics.StackTrace
Console.WriteLine(st.GetFrame(1).GetMethod.Name) ' method that
invoked the event
End Sub

Sub test()
c.raise1()
c.raise2()
End Sub
End Class

End Module

The system.diagnostics namespace provides a class that allows you to find
out the current call stack - index 0 is the current method, 1 the one that
called it, and so on. Assuming the form uses different methods to invoke
each event, you might be able to find out which event was invoked by
checking which method called it. Then again, it is possible that a single
message handling method invokes several of these events - in that case,
this won't work.
If it doesn't work, well, at least we've learned something new.

Have fun
Alex
 
Back
Top