Posts filed under 'VB.NET Tutorials'

How To Pass Data Between Forms in VB.NET

Using overloading to pass dataA common question that comes up rather often in VB discussion forums is how to pass data between forms. One of the common solutions offered are to use global variables in one way or another, for example, creating a module specifically for holding these values. These methods have all the typical problems with associated with globals. Another common strategy is to make the desired data available via properties on the forms. This can work in some cases but also can lead to undesirable interdependencies between forms. However, there is another approach that is often overlooked.

This article is about this overlooked strategy, overloading the New, Show or ShowDialog methods of forms. The reason this gets overlooked is that it isn’t obvious, particularly to someone who is new to programming or those who’ve transitioned from VB6. Forms get thought of as a special case because they contain a lot of generated code. But, actually, behind the scenes, they’re just another class in the application. And, like other classes, we can adapt them to our needs by overloading their base methods.

New

As with other classes with no explicit New method, a parameter-less New method of a form is automatically generated by the .NET compilation process. If we want to add our own overload method, we just add it to the code for it to our form. Here’s what it should look like:

Public Sub New(ByVal customerOrder As Order)
    Me.InitializeComponent()
    LoadOrder(customerOrder)
End Sub

In this example, we’re passing in an order object to our new form. Note that we call the InitializeComponent method first to create the controls on the form. This method is generated by VB.NET and is located in the [form name].Designer.vb file that contains a partial class definition for our form. Once the controls are created, we can then call our routine to load data into the controls.

When you define your own New method you will lose the default parameter-less New method and thus lose the VB.NET created default instance. To restore the default instance, add your own Public Sub New() as shown here:

Public Sub New()

    ' This call is required by the Windows Form Designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.

End Sub

In Visual Studio, if you just type in the first line and press enter the rest will be generated for you. If you don’t add this routine, you will need to explicitly create instances of the form using your New method as in this example.

Dim frmCustomerOrder As New frmOrder(CurrentOrder)

You can use this way to insure that the form is properly loaded with data before it is displayed.

Show

Show, as you probably know, displays the form modelessly and does not return a value. This function comes with one overload which allows you to specify the owing window/form. To continue our example, let’s add a Show method that takes our order object.

Public Overloads Sub Show(ByVal customerOrder As Order)
    If customerOrder Is Nothing Then
        'load up order defaults
    Else
        'load from parameter
    End If
    MyBase.Show()
End Sub

Notice at the end we call the form’s base class to show the form. If you don’t have this line, then the form will not be displayed.

While the stock methods don’t return a value, did you know that you can write a version of this method that returns a value? You can. Here’s an example:

Public Overloads Function Show(ByVal OrderID As Guid, ByVal viewOnly As Boolean) As Boolean
    If LoadCustomerOrder(OrderID) Then
        SetupControls(viewOnly)
        MyBase.Show()
        Return True
    Else
        Return False
    End If
End Function

In this example, we return a True if the order is found and the form is loaded but a False if the order ID isn’t found. Remember that processing doesn’t stop at the MyBase.Show() to wait for user input but continues onward.

ShowDialog

ShowDialog shows the target form modally and, in its built-in methods, it returns a Windows.Forms.DialogResult value. Here’s an example of overloading it

Public Overloads Function ShowDialog(ByRef newCustomerOrder As Order) As Windows.Forms.DialogResult
    newCustomerOrder = New Order
    'load up order defaults
    Return MyBase.ShowDialog()
End Function

In this case we’re passing in an order object by reference so that the dialog can modify it and return it and we’re returning a DialogResult like the other overloads. Also, just like with the show method, we need to call the base class to show the dialog.

Note, however, that we don’t need to return the DialogResult value, we can return anything we want, as seen in this code that returns an order object.

Public Overloads Function ShowDialog(ByVal orderID As Guid) As Order
    Dim ExistingCustomerOrder As New Order(orderID)
    'load up order defaults
    If ExistingCustomerOrder.OrderDetail IsNot Nothing Then
        If MyBase.ShowDialog() = Windows.Forms.DialogResult.OK Then
            Return ExistingCustomerOrder
        Else
            Return Nothing
        End If
    Else
        Return Nothing
    End If
End Function  

It is probably best for consistency in most cases to return the same value as the default methods though.

That’s how you can pass values around between forms without having to use global variables (or work-alikes) or properties. Let me know if you have any questions, additions, or corrections by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

16 comments September 28th, 2007

Introduction to Nullable Types in VB.NET

Yeah, well, sometimes nothin' can be a real cool hand.In .NET nullable data types are data types that can be set to a null reference or, in VB.NET terms, Nothing. They can either contain a value or have no value at all. Reference data types, like strings and classes, are nullable. However, Value types, such as integers and dates, are not nullable. If you set a value type to Nothing the result is a default value such as 0 for numeric types or #1/1/0001 12:00:00 AM# for dates.

As you can probably guess, there may be times when you will need to have value data types that can be Null/Nothing. For example, a database column of date values could be Null in the database and you want your class to reflect this situation. In the .NET Framework 2.0, we have the Nullable class and the Nullable structure that allows us to add the ability to have a value of Nothing to an underlying value type.

In practice, we will want to use the Nullable structure since it supports Generics and thus allows you to define a specific data type. This gives you greater type safety and it’s easier to work with.

To start things off, let’s create a fragment of a class that uses a Nullable structure as a property.

Public Class Orders
    '
    ' Other property variables
    '
    Protected _orderShippedOn As Nullable(Of Date) 

    '
    ' Other methods and properties
    '

    Public Property OrderShippedOn() As Nullable(Of Date)
        Get
            Return _orderShippedOn
        End Get
        Set(ByVal value As Nullable(Of Date))
            _orderShippedOn = value
        End Set
    End Property
End Class

In this example, we have an order shipped on date value. Since we will want the order in the system prior to shipping it out the door, the value in our database will be Null until this event happens. We don’t want to hard code values like this in several places in our application…

If CurrentOrder.OrderShipDate = #12:00:00 AM# Then

…to fake out null values. Instead, we wrapper our dates in a Nullable class.

HasValue and Value

But, you’ll notice that if you code a line like this…

 
If CurrentOrder.OrderShippedOn Is Nothing Then

…we’ll get an error. This is because we’re still dealing with a structure, not a class. Here’s what our code should look like:

If Not CurrentOrder.OrderShippedOn.HasValue Then
    dtpOrderShipDate.Value = Now
Else
    dtpOrderShipDate.Value = CurrentOrder.OrderShippedOn.Value
End If

The HasValue property returns a Boolean value that lets us know if there is a value or not. Then, when we want to retrieve the value to load it into a Date Time Picker control, we use the Value property. This allows us to return the correct type for the control. You can’t use = or Is to compare a Nullable type, you have to use the HasValue or Value properties.

Loading Nulls from the Database

Now let’s look at how we should load our object from our database. In this example, we’re assuming that we’re loading our object from a DataRow.

If orderDataRow.Item("ShipDate") Is DBNull.Value Then
    _orderShippedOn = Nothing
Else
    _orderShippedOn = CType(orderDataRow.Item("InventoryDate"), Date)
End If

We have to check for a Null value since we can’t convert a DBNull to a Date.

That’s it for this introduction to Nullable types. I hope you’ve found it useful. Let me know if you have any questions, additions, or corrections by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

5 comments September 27th, 2007

How To Update Controls Using BackgroundWorker in VB.NET

BackgroundWorker Paints a FormThe .NET Framework 2.0 BackgroundWorker class makes it easy to code simple threading into your applications. However, a common question that gets asked in VB related forums is, “How do I update a control, or controls, from the worker thread?”. Many people seem to be in search of a simple explanation of how to do this. In this article we’ll create a quick and easy example program that will walk you through the steps.

Getting Started

First, we will need to create a new Windows application. On our form we’ll add two buttons, btnStart and btnCancel, a progress bar, prgThread, and a listbox, lstValues. You may also want to import System.ComponentModel into the project namespace or onto the form or you can just spell it out like I’m doing below.

Next we’re going to add code. First, we declare the BackgroundWorker object, TestWorker. Note that we’re declaring it with events so that the event structure is built automatically.

'
Private WithEvents TestWorker As System.ComponentModel.BackgroundWorker
'
'

Now, code is added for the start button, btnStart.

Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
    btnStart.Enabled = False
    btnCancel.Enabled = True
    lstValues.Items.Clear()
    prgThread.Value = 0
    TestWorker = New System.ComponentModel.BackgroundWorker
    TestWorker.WorkerReportsProgress = True
    TestWorker.WorkerSupportsCancellation = True
    TestWorker.RunWorkerAsync()
End Sub

First, we disable the start button and enable the cancel button. Next we reset the values for our listbox and and progressbar. Now we’re ready to create our BackgroundWorker object. Notice that we tell it that we want to have it report progress and support cancellation. Finally, we tell it to run the worker.

The Worker

Here’s the code for our worker thread. This code is contained in the DoWork event. All it’s doing is looping 100 times and reporting the progress and sleeping 100ms between iterations. We also check for a cancellation state.

Private Sub TestWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles TestWorker.DoWork
    Dim ListText As String
    For Value As Integer = 0 To 100
        If TestWorker.CancellationPending Then
            Exit For
        End If
        ListText = String.Concat("Item #", Value)
        TestWorker.ReportProgress(Value, ListText)
        Threading.Thread.Sleep(100)
    Next
End Sub

You can also see that in the ReportProgress function call that we’re passing in the current value and a string.

Updating Form Controls

In the ProgressChanged event, we get to process our values from our DoWork method. Here’s the code:

Private Sub TestWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles TestWorker.ProgressChanged
    prgThread.Value = e.ProgressPercentage
    lstValues.Items.Add(e.UserState)
End Sub
'

In this routine, the progress bar and the listbox are updated with values from the worker thread. Remember that the UserState value is an object and will require conversion if you can’t use an object type.

Canceling the Worker

Now, what if you want to cancel the worker? Here’s the code that goes into our cancel button’s Click event:

Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
    TestWorker.CancelAsync()
End Sub
'
'

Here we call the CancelAsync method. However, this only sets a flag and, as shown above, our DoWork method has to check for a CancellationPending state. Otherwise, the work will continue until the DoWork routine is exited.

Finishing Things Up

When the work has been completed or canceled, the RunWorkerCompleted method is called. In our program, this allows us to reset our buttons.

Private Sub TestWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles TestWorker.RunWorkerCompleted
    btnStart.Enabled = True
    btnCancel.Enabled = False
End Sub

That’s how it’s done in a nutshell. Of course, handling multi-threading in your applications can become very tricky. It is recommended that you further review how to avoid problems with threading before implementing it.

Let me know if you have any questions about BackgroundWorker or if you have any suggestions or thoughts about this example by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

24 comments September 24th, 2007

Introduction to My.Computer.Network

My.Computer.Network: An Internet ShortcutMy.Computer.Network is another VB.NET My Namespace shortcut class that you can use to handle simple network and Internet operations. In this article we’ll examine the basics of this class with some code examples along the way.

These functions are essentially easy-to-use wrappers for objects found in the System.Net namespace. If you need more than what this class provides then you should look there.

IsAvailable

As you might guess, this property indicates if there is an available network connection or not. The hitch with this function is that it doesn’t tell you much about the connection, it only says if the computer has one or not. For example, a computer might have a local network connection but the Internet connection could be down but this property would return True. Therefore, you should combine this technique with the Ping function to insure that a remote location is available as seen in this code example:

If My.Computer.Network.IsAvailable Then
    If My.Computer.Network.Ping("192.168.100.1") Then
        My.Computer.Network.UploadFile(LocalFileName, RemoteAddress)
    End If
End If

NetworkAvailabilityChanged

This event is raised when the network connectivity changes but, like IsAvailable, it’s not capable of distinguishing between local and remote changes. Therefore, it really isn’t that useful in many situations. It might be handy in a web service client app, for example, a single computer at a remote small store location without a permanent or iffy Internet connection.

This event is built into the MyApplication partial friend class so, if you’re using the Windows Application Framework you just have to add code to the following built-in routine:

Partial Friend Class MyApplication

    Private Sub MyApplication_NetworkAvailabilityChanged(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.Devices.NetworkAvailableEventArgs) Handles Me.NetworkAvailabilityChanged
        If My.Computer.Network.IsAvailable AndAlso My.Computer.Network.Ping("192.168.100.1") Then
            'code to handle/report connection available
        Else
            'code to handle/report connection down
        End If
    End Sub
End Class

Ping

As we see in the code examples above Ping does a simple check to see if a remote target computer responds and returns a boolean saying if the check was successful or not. You can use an IP address, like in the examples above, or a DNS resolvable name. This means that for Internet addresses you would not include protocol prefixes like “http://” or “ftp://” but only the name. You can also provide a timeout for the ping in milliseconds and the default is 500ms, a half-second. Increasing this value can be useful if you’re dealing with a slow dial-up connection. Always verify any user input for this call to prevent unwanted exceptions. Note that some servers use firewalls and other methods to protect themselves against ping attacks and the function may return a False when there actually is a system at that address.

Here are some examples of this function:

If My.Computer.Network.Ping("192.168.100.1") Then

...

If My.Computer.Network.Ping("192.168.100.1", 2000) Then

...

If My.Computer.Network.Ping("vbnotebookfor.net") Then

....

If My.Computer.Network.Ping("www.google.com") Then

...

' Will Cause PingException
If My.Computer.Network.Ping("http://www.google.com") Then

DownloadFile and UploadFile

Download, of course, copies a file from a remote location to a local location while Upload does the opposite. Overloads provide several options beyond just the file names or URLs. As with regular file copies the source and target locations have to be accessible or an exception will occur. Therefore, it’s a good idea to do some basic validation before calling either of these routines. Unlike the Ping function, you do need to include a protocol such as “http://” or “ftp://”.

There are overloads for credentials. You can use either clear text username and password parameters (not recommended when you’re transmitting sensitive information!) or, if you’re connecting to a system that supports it, an ICredentials object.

Both have a connection timeout value with a default of 100 seconds. Remember this value is in milliseconds though. As with Ping, this parameter is useful when you have slow conditions.

Both also provide a user interface option where the user will be shown a progress dialog and can cancel the transfer. You will want to set an action to be taken when the user cancels since the default is an exception.

Download also has an option for you to specify if a local file can be overwritten or not. Upload doesn’t offer this so you may get back exceptions if the remote server doesn’t permit the overwrite. It is important to check for exceptions in these methods since there are so many things that can go wrong with remote file transfers.

Here are some simple code examples:

1. Upload file with exception handling, connectivity check, clear text username/password, and showing UI

Try
    If My.Computer.Network.IsAvailable AndAlso My.Computer.Network.Ping(RemoteServer) Then
        My.Computer.Network.UploadFile(LocalFile, RemoteLocation, UserName, Password, True, 10000)
    End If
Catch ex As Exception
    'exception handling code here
End Try

2. Download file with exception handling and connectivity check

Try
    If My.Computer.Network.IsAvailable AndAlso My.Computer.Network.Ping(RemoteServer) Then
        My.Computer.Network.DownloadFile(RemoteLocation, LocalFile)
    End If
Catch ex As Exception
    'exception handling code here
End Try

3. Upload file with exception handling, connectivity check and the current user’s credentials

Try
    If My.Computer.Network.IsAvailable AndAlso My.Computer.Network.Ping(RemoteServer) Then
        My.Computer.Network.UploadFile(LocalFile, RemoteLocation, My.User.CurrentPrincipal)
    End If
Catch ex As Exception
    'exception handling code here
End Try

I hope you’ve found this introductory overview of the My.Computer.Network class useful. If you have anything to add or if you have any questions, please feel free to leave me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

8 comments September 21st, 2007

Welcome to Math Class

Today's Subject: System.MathThe .NET math class provides you with several handy math routines you can use even if you’re not doing complex trigonometric or logarithmic functions. In this article we will take an introductory look at the non-trig, non-log, functions and how to use them in your code.

Abs

This is an old familiar command to VB Classic and BASIC programmers. It returns the absolute value of a number and it accepts SByte, Short, Integer, Long, Decimal, Single, and Double data types in its overloads. Remember it returns the same type of data that you send it. It doesn’t do conversions between numeric types like previous versions of VB and BASIC when you have Option Strict On (which you should always have on). You’ll need to handle the conversion yourself.

Also, don’t forget that you have to prefix it with Math or use “Imports System.Math” in your module or project namespace. Here’s an example of this function:

Dim NewValue As Integer = Math.Abs(OldValue)

BigMul

If you’re working with big integers this function can be quite helpful in helping you avoid overflow exceptions. Remember the product of multiplying two Int32 values is an Int32 value. If your product exceeds the upper or lower Int32 range you’ll get an exception. To avoid this situation, you can use BigMul to multiply two Int32 values and return a Int64 value. Here’s a simple example:

Dim ABigNumber As Integer = 40000000
Dim AnotherBigNumber As Integer = 40000000
Dim ABigProduct As Int64 = Math.BigMul(ABigNumber, AnotherBigNumber)

DivRem

First BigMul and now DivRem, did somebody at Microsoft not get the memo about using meaningful function names? Anyway, DivRem calculates and returns the quotient of two integers, either 32 or 64 bit, plus it also returns the remainder in an output parameter. This function is handy if you want to get both the quotient and remainder in a single swoop. Here’s an example:

Dim TestIt As Integer = 578
Dim TestToo As Integer = 75
Dim TestValue As Integer
Dim TestRemainder As Integer
TestValue = Math.DivRem(TestIt, TestToo, TestRemainder)
Debug.Print(String.Concat(TestValue, " | ", TestRemainder))

Output Value: 7 | 53

Remember to make sure that you don’t accidentally divide by zero here.

IEEERemainder

This function is sort of like DivRem except that it’s for doubles and that it returns the remainder, not the quotient (which gets dropped). Kind of an inconsistant design if you ask me. Here’s an example of this function:

Dim TestAgain As Double = 194.89482
Dim RemainderTest As Double = Math.IEEERemainder(TestAgain, Math.PI)

Output Value: 0.116075477432837

Note the use of the Pi constant value in this example.

Sign

Sign is a simple, straightforward function. It returns -1 if the target number is negative, 0 if the number is zero, and 1 if the number is positive. There are overloads that will work with any of the signed number types. Here’s an example:

Select Case Math.Sign(TestAgain)
    Case 1
        'positive number action
    Case 0
        'zero action
    Case -1
        'negative number action
End Select

Ceiling and Floor

These functions are useful with decimal and double values where you want to obtain the nearest whole number that’s either greater than (ceiling) or less than (floor) of the given number. This could be useful in a custom rounding routine. Here are some examples and the result of the operation

Dim MyValue as Double
MyValue = Math.Ceiling(194.89482)

Output Value: 195

MyValue = Math.Floor(194.89482)

Output Value: 194

MyValue = Math.Ceiling(-194.89482)

Output Value: -194

MyValue = Math.Floor(-194.89482)

Output Value: -195

Truncate

Truncate is like the old VB6/MSBASIC Fix function (this function is still in the Microsoft.VisualBasic Namespace). It simply drops the decimal portion of the target decimal or double number. Here’s the example

Dim IntValue As Integer = CInt(Math.Truncate(TestAgain))

Notice that this function also returns a double or decimal rather than an integer and this requires conversion unless you’re unwisely not using Option Strict On.

Max and Min

These functions respectively return the larger or lesser of the two numbers passed in. These functions could be quite useful for sorting routines or for random selection routines.

LowestPrice = Math.Min(NewProduct.Price, OldProduct.Price)

Pow

Pow simply raises an number to a specified power, just like the ^ operator does. I’d just use the operator myself.

Debug.Print(String.Concat(7 ^ 8))
Debug.Print(String.Concat(Math.Pow(7, 8)))

Output Value for both: 5764801

Round

I covered Round in depth in this earlier article: What You Should Know About Rounding in VB.NET

I hope this article has given you a good overview of the Math class functions. While there is some redundancy there are few hidden gems as well. As always, let me know what you think by leaving a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

1 comment September 19th, 2007

Next Posts Previous Posts


Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles

Categories

Most Recent Articles

Feeds

 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities

Archives