Google Answers Logo
View Question
 
Q: VB.NET new usercontrol events ( Answered 5 out of 5 stars,   0 Comments )
Question  
Subject: VB.NET new usercontrol events
Category: Computers > Programming
Asked by: sceleratus-ga
List Price: $4.50
Posted: 31 Mar 2004 17:39 PST
Expires: 30 Apr 2004 18:39 PDT
Question ID: 323258
I'm an intermediate programmer, relatively new (1-2 yrs light
experience) to event-driven OOP.

I have created a runtime-resizable button as a usercontrol in visual
basic .net (standard). I would like for the command button's
btnButton_Click() event to be accessible outside of the control itself
(i.e. from the form on which the usercontrol resides). I am assuming
that I will have to write a new event that handles the click event
within the usercontrol, yet still has public accessibility.

A basic coverage of writing new events (in general & in this instance)
would be very much appreciated. I do have MSDN installed, but i am
looking for something a bit easier to grasp.
Answer  
Subject: Re: VB.NET new usercontrol events
Answered By: cyclometh-ga on 31 Mar 2004 19:34 PST
Rated:5 out of 5 stars
 
Hi sceleratus-ga!

I'm pleased to be able to help you with an quick (and hopefully
somewhat painless) introduction to Events in Visual Basic. Some of the
code snippets may wrap incorrectly depending on your screen width; if
so, copy and paste them into Notepad or a text editor to see them more
clearly.

You may also be aware of some of these points already; I am going with
a "ground-up" approach that assumes little or no knowledge about
events in Visual Basic .NET specifically, but I am assuming that you
are familiar with OO programming techniques and principles, and to
events in general, which I have guaged from your original question.

Events in .NET are based around "delegates", which are a feature of
.NET that allows you to do things like implement custom callbacks and
so on. VB.NET allows you to create events in two ways- the "easy" way
and the "hard" way, although neither is really that tough.

I'll first describe a couple of simple ways to create events in
VB.NET, and I'll then describe some other neat things you can do with
them. I'll then describe the "standard" way to create Events in Visual
Basic .NET.


Simple Events

First, the simplest way to create an event is to simply declare it in
your class (in this case, your custom control class), like in the
following code snippet (I have removed most of the code inserted by
Visual Studio for clarity)

-----------

Public Class btnControl
    Inherits System.Windows.Forms.UserControl


	Public Event ButtonClick()


	End Sub
End Class
----------

As you can see, I have declared an event using the Event keyword-

Public Event ButtonClick()

After adding a usercontrol or modifying one, you have to rebuild your
project in order to see the changes appear in the designer.


Adding Event Handlers

After rebuilding, you should see your user control appear in the "My
User Controls" tab of the Toolbox. You can then drag an instance of
this control to a form. Once you've done this, open the form in code
view. In the upper left corner of the code screen, select the name of
your control (in my case, it's BtnControl1) from the list. Then you'll
be able to view all the events associated with that control in the
drop-down list on the right.

At this point, you may be wondering why there are so many events when
we only defined one- the answer is that because this example control
(btnControl) is a subclass of System.Windows.Forms.UserControl, it
inherits all the events of its parent- many of which are extremely
useful in Windows Forms programming.

If you created an event called ButtonClick in your control, you'll see
it in the list- you'll also see one called Click, which is a standard
event associated with all Windows controls. NOTE: You should not name
your event "Click" or it will cause a conflict with the base class'
Click event.

If you want to create a handler for your custom ButtonClick event, you
should select the name of the control from the code window, then the
event, which will cause the IDE to automatically generate an event
handler for you. You could also manually enter the event handler code,
which would look like this:


---------------
Private Sub BtnControl1_ButtonClick() Handles BtnControl1.ButtonClick

	MessageBox.Show("Button on user control was clicked!")

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

The key portion to this is the "Handles" keyword. It tells VB.NET that
this method will be invoked automatically by the runtime when your
control fires its ButtonClick event. The method can have any name you
like- it does not have to be "BtnControl1_ButtonClick", although this
is the usual convention. However, the method's "signature" must be the
same as the event that it is handling- meaning that the number of
arguments and types of arguments must be identical. If they are not,
the IDE will tell you that the method signature does not match.


Raising (Firing) Events

At this point, we've created a User Control, added an event to that
control, added that control to a form, and have implemented an event
handler to handle our custom event. However, one thing is missing-
currently, the event won't ever be fired! If you tried to test this,
you may have noticed that the MessageBox call we placed in the method
above is never invoked.

In order for a control (or any class) to raise an event, it must use
the "RaiseEvent" statement. Since we want this event to be raised when
the button is clicked, we must add an event handler to the control
which will handle the button's Click event and raise our event in
turn. The following code snippet demonstrates this:

----------------
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

		'Do some other work here if need be
		RaiseEvent ButtonClick()
End Sub
-----------------

Remember that this method is added to the control, not the form! Note
the Handles clause for this method- it's going to get the Click event
for the button on the User Control and perform some operations if need
be, then will fire (raise) our custom event. Don't forget to rebuild
your project for the changes to appear to the forms using the control.
In a sense, we've just "wrapped" the Click event for the Button on the
control with our ButtonClick event.


Declaring Events with Arguments

You can also pass arguments with events, just like with any method or
function call. In order to do this, you would add the arguments you
wanted to the Event declaration:

Public Event ButtonClickWithArgs(ByVal ClickTime as Date)

In order to raise this event, you would have to do something like this:

RaiseEvent ButtonClickWithArgs(Now)

Of course, any handlers of this event would have to have a Date
argument, or the IDE will fail to compile the project and return an
error about mismatched method signatures. A method that handles this
event will recieve any arguments passed to it just like any other
method or function call.


Best Practices with Events

This section describes how Microsoft likes to do things- you're
certainly not required to follow their model, but it's often a good
idea, especially if you plan to distribute your code, as other
developers will be more familiar with the standard design patterns
used by Microsoft.

In general, you will notice that Microsoft codes its events that are
already in the .NET Framework classes following a general pattern.
Here is a standard event handler for a button object's Click event:

Private Sub Button1_Click(Byval sender as Object, ByVal e as EventArgs)

Most event handlers defined in the .NET framework follow this pattern,
and it's probably a good idea to emulate it for most of your events.
In this model, a variable of type Object is passed, and represents the
object or class that raised the event. The second argument is an
instance of an EventArgs class, which is defined in the .NET
Framework.

The EventArgs class is essentially an empty class- it contains no
event data, and is used when raising an event that passes no state
information to handlers of that event. There are many subclasses of
EventArgs that do provide state information, such as the
KeyPressEventArgs class, which is passed when a KeyPress event is
generated.

If we wanted to create a more "Microsoft-like" version of our
ButtonClicked event from above, it would be coded as follows:

Public Event ButtonClicked(ByVal sender as Object, ByVal e as EventArgs)

And then when we wanted to raise the event, it could be done like so:

RaiseEvent ButtonClicked(Me, New EventArgs())

If you find that you wish to pass events that contain state
information, it is generally a good idea to write a subclass of
EventArgs that has that state data as properties, and create a new
instance of that class to pass when the event is raised. Using our
example from before, we could create a new subclass of EventArgs:

------------------
Public Class MyCustomEventArgs
	Inherits EventArgs
	Private _clickTime As Date

	Public Sub New(ByVal BtnClickTime As Date)
		_clickTime = BtnClickTime
	End Sub
	Public Property ClickTime() As Date
		Get
			Return _clickTime
		End Get
		Set(ByVal Value As Date)
			_clickTime = Value
		End Set
	End Property
End Class
--------------------

which we can use in a custom event handler. The following Event declaration:

Public Event ButtonClickWithTime(ByVal sender as Object, ByVal e as
MyCustomEventArgs)

allows us to use the following RaiseEvent statement in the Button's
Click event handler on our custom control:

---------------------
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
		Dim custEvtArgs as MyCustomEventArgs
		custEvtArgs=New MyCustomEventArgs(Now)
		'Do some other work here if need be
		RaiseEvent ButtonClickWithTime(Me, custEvtArgs)
End Sub
---------------------

Or you could make it more simple like this:

---------------------
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
		'Do some other work here if need be
		RaiseEvent ButtonClickWithTime(Me, New MyCustomEventArgs(Now))
End Sub
---------------------


Events in Classes (not controls)

Events in a custom class are done identically to those in a control-
however, when you create an instance of that class in your code, you
should declare it as "WithEvents", like so:

Dim WithEvents MyObj as MyObject

Which will allow you to create event handlers for any events the
object raises. Without the WithEvents keyword, you won't receive any
events from custom classes. The VB.NET IDE automatically declares
controls to be WithEvents when you place them on the visual designer,
however.


AddHandler and RemoveHandler

You don't have to use the "Handles" clause with an event in order to
handle that event. You can dynamically connect and disconnect events
with the AddHandler and RemoveHandler statement. I won't go into the
details here, as it would needlessly complicate an already lengthy
discussion, but the basics are that you create a method that matches
the signature of the event you want to handle as normal, but you leave
out the "Handles" clause. Then in your code, you call AddHandler to
connect an event to your event handler, and RemoveHandler to
disconnect the event. You'll have to use the AddressOf operator in
order to make this work. There are good examples in the MSDN
documentation as well, and these make a great place to start for more
advanced event handling topics.


Final Notes

I would recommend bringing up the MSDN Index and looking at the
following topics (set your filter to "Visual Basic .NET and Related"
for easier searching)

Events and Delegates
Event Keyword
Delegate Keyword
RaiseEvent Keyword
EventArgs Class
AddHandler
RemoveHandler
AddressOf Operator

[MSDN website]
http://msdn.microsoft.com
Contains the entire .NET Framework documentation set, as well as the
MS Knowledge Base, which is an invaluable resource.

Thank you very much for the opportunity to answer this question for
you- I hope the information I presented was useful (and not
overwhelming). If you have any questions or would like clarification,
please do not hesitate to ask- I can provide additional simple code
snippets or pointers to other resources if you need them.

Thanks for using Google Answers!

Best regards,

Cyclometh-ga

Clarification of Answer by cyclometh-ga on 01 Apr 2004 02:18 PST
Thank you for both the feedback and the tip- they're appreciated! And
thanks again for using Google Answers.

Cyclometh-ga
sceleratus-ga rated this answer:5 out of 5 stars and gave an additional tip of: $1.00
Very good answer. Clear, concise, straightforward. Almost too simple!

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy