Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

July 22, 2009

User Control Events in VB and C#

Filed under: C#,VB.NET,WinForms @ 3:58 pm

There are many things in VB.NET and C# that are very similar. So if you know that basic syntax of both languages, it is relatively easy to convert a few lines of code from one to the other.

Not so much with events. This is one area where it is easy to get tripped up when you have to convert code from one language to the other.

To demonstrate how to define events in VB vs C#, this example is a WinForms user control that raises a single custom event. It is a very simple user control that inherits from a TextBox. The point is not to demonstrate the proper way to create a user control, but rather just to focus on adding an event to the user control.

The event is a ValueChanged event. This event is raised when the associated TextBox TextChanged event occurs. While this might be less than useful, it provides a simple example of defining event in VB and C#.

One other note before diving into the code. The event in this post follows the suggested pattern of defining event parameters of type object and eventArgs (or a subclass thereof). If you are coming from earlier versions of VB or C, you may be used to creating events with other types of parameters.

For example, you could do this in VB:

Public Class SampleUserControl
  ‘ Declare an event
  Public Event ValueChanged(value as Integer)

  Private Sub SampleUserControl_TextChanged(ByVal sender As Object, _
              ByVal e As System.EventArgs) Handles Me.TextChanged

     ‘ Raise the event
     RaiseEvent ValueChanged(42)
  End Sub
End Class

While this makes the coding extremely easy (what you see above is all you need), it does not follow the pattern or best practices as defined by the “Framework Design Guidelines”.

So lets get to the real example. Since the code is so different, instead of showing a little at a time in both languages, this shows the VB code first. Then it goes through the same features using C#.

In VB:

Public Class SampleUserControl
  ‘ Declare an event
  Public Event ValueChanged(ByVal sender As Object, _
                  ByVal e As ValueChangedEventArgs)

  Private Sub SampleUserControl_TextChanged(ByVal sender As Object, _
                  ByVal e As System.EventArgs) Handles Me.TextChanged
        Dim tb As TextBox = DirectCast(sender, TextBox)
        Dim value As Integer = 0
        If IsNumeric(tb.Text) Then
                value = CType(tb.Text, Integer)
        End If
       ‘ Raise the event
        RaiseEvent ValueChanged(sender, _
                  New ValueChangedEventArgs(value))
  End Sub
End Class

This class is a user control that inherits from a TextBox. In VB, by convention the inherits statement is in the associated designer file (SampleUserControl.Designer.vb):

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class SampleUserControl
    Inherits TextBox
    …

End Class

The code in the class first declares the event. Notice that it uses the standard sender and e parameters. It then raises the event when the associated TextBox text is changed. If the TextBox Text property value is numeric, it passes the value as part of the event arguments; otherwise, it passes 0.

Since the ValueChanged event required additional data associated with it, it did not use the standard EventArgs class. Rather, it defined its own ValueChangedEventArgs class:

Public Class ValueChangedEventArgs
    Inherits EventArgs

    Private _NewValue As Integer
    Public Property NewValue() As Integer
        Get
            Return _NewValue
        End Get
        Set(ByVal value As Integer)
            _NewValue = value
        End Set
    End Property

    Public Sub New(ByVal currentNewValue As Integer)
        NewValue = currentNewValue
    End Sub

End Class

This class inherits from EventArgs. Any desired properties can be added to this class. In this case, only one property was added for the new value. The constructor requires that this new value be passed in as a parameter.

So using a specialized EventArgs class required a little more code than the first VB example. But this is still basically straightforward.

To summarize the steps:

  1. Declare the event in the User Control.
  2. Raise the event in the User Control where appropriate.
  3. Define the class that inherits from EventArgs.

So now let’s move on to C#:

// Declare a delegate
public delegate void ValueChangedEventHandler(object sender,
                                  ValueChangedEventArgs e);

public partial class SampleUserControl : TextBox
{

    public SampleUserControl()
    {
        InitializeComponent();
    }

    // Declare an event
    public event ValueChangedEventHandler ValueChanged;

    protected virtual void OnValueChanged(ValueChangedEventArgs e)
    {
        if (ValueChanged != null)
            ValueChanged(this,e);
    }

    private void SampleUserControl_TextChanged(object sender,
                                     EventArgs e)
    {
        TextBox tb  = (TextBox)sender;
        int value;
        if (!int.TryParse(tb.Text, out value))
            value = 0;
        // Raise the event
       OnValueChanged( new ValueChangedEventArgs(value));
    }

}

This code declares a delegate outside of the class. The class is a user control that inherits from a TextBox.

The first set of code is the constructor for the user control. The code then declares the event using the delegate.

Since there is no RaiseEvent function in C#, you have to create a method that generates your event. This is the OnValueChanged method shown above. The convention is to use the word “On” and the name of your event. The TextBox TextChanged event then calls OnValueChanged to raise the event.

Since the ValueChanged event required additional data associated with it, it did not use the standard EventArgs class. Rather, it defined its own ValueChangedEventArgs class:

public class ValueChangedEventArgs : EventArgs
{
    public int NewValue { get; set; }

    public ValueChangedEventArgs(int newValue)
    {
        NewValue = newValue;
    }
}

This code is very similar to the VB code. This class inherits from EventArgs. Any desired properties can be added to this class. In this case, only one property was added for the new value. The constructor requires that this new value be passed in as a parameter.

To summarize the steps:

  1. Declare a delegate outside of the user control class.
  2. Declare the event in the User Control of the delegate type.
  3. Create a method to generate the event.
  4. Call the method to raise the event in the User Control where appropriate.
  5. Define the class that inherits from EventArgs.

When a form uses your user control, it can hook up the event as needed.

In VB:

Private Sub SampleUserControl1_ValueChanged(ByVal sender As Object, _
                           ByVal e As ValueChangedEventArgs) _
                           Handles SampleUserControl1.ValueChanged
    Debug.WriteLine("Made it to the event test: " & e.NewValue)
End Sub

This code works because in the designer, the user control is automatically declared WithEvents:

Friend WithEvents SampleUserControl1 As _
                               SampleApplication.SampleUserControl

Alternatively, you can use the Addhandler statement to hook up the ValueChanged event.

In C#:

private void sampleUserControl1_ValueChanged(object sender, 
                           ValueChangedEventArgs e)
{
    Debug.WriteLine("Made it to the event test: " + e.NewValue);
}

For this code to work, you need to use the designer to hook up the events, (which generates the following line of code in the designer file) or add this line of code in the form:

sampleUserControl1.ValueChanged += sampleUserControl1_ValueChanged;

So C# and VB can provide the exact same functionality, but with different steps to get there.

Enjoy!

3 Comments

  1.   Gilbert — July 28, 2009 @ 4:26 am    Reply

    Hi Deborah,
    Thank you for taking the time to put this beautiful article. Im newbie in C# and this is just what I was looking for, exactly something like this.
    After one day of trying without any success, I found I made two slight omissions, that the article not mention about these.
    1. You need to use the control user designer to hook up the SampleUserControl_TextChanged.
    2. The event handling method that consume the event must be.
    private void sampleUserControl1_ValueChanged(object sender, NamespaceName.ValueChangedEventArgs e)

    Cheers from Bolivia.

  2.   BillB — August 25, 2010 @ 8:48 am    Reply

    Thanks much for the article; it very much helped this winforms newbie. I used the technique for a custom event in a Form class, the details of which I took a few hours to write up.

    http://www.billb.name/it/Custom-Events.asp

    I used the generic EventHandler delegate that comes with the Framework instead of defining my own delegate. But then I thought that if you don’t want to send data to a subscriber in an EventArgs class, maybe you don’t have much data to send. Then I figured a custom delegate would be in order and I could eliminate having to code an EventArgs class.

  3.   stentor — May 9, 2011 @ 4:36 pm    Reply

    VB’s approach to events is so much less of a pain in the ass. And what’s with the CSharp folks at MS and Intellisense? Did they forget that only anal retentives like typing out everything and calling everyone who doesn’t lazy? Or is they’re just still catching up?

    With VB, in let’s say class that inherits a control, you select Protected Overrides with intellisense, the dropdown gives all the OnWhatever event overrides, you select one, and bingo. Only thing you have to type is what goes inside.
    What am I missing here?

    WithEvents is handy too. Suppose I have a class that
    can’t inherit some object that will source events because the class is already preoccupied with another inheritance. Well, then I can just encapsulate that object with a private variable declared withevents. Then the class module dropdowns give all the events for that object, I select what I want, voila. No hooking up handlers and declaring delegates, unless of course I have a special need for that, like aggregating events from disparate sources, object arrays, something done on the fly etc.

    All this nice bread and butter timesaving stuff that the designer does for you automatically in VB, yes it is done because after all that was the original idea behind computers, to do the repetitive stuff for the creators, the humans.

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2019 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs