Visual Basic .Net – Binding to Windows Forms Controls

1 comment

Posted on 7th June 2010 by Admin in Visual Basic .Net

,

The .NET Framework brings a wide variety of controls to the developer. The Windows Forms controls are found in the System.Windows.Forms namespace, and the vast majority of them support data binding. In general, data binding to a control is far from challenging. It requires that you use an in-memory data store and can usually accept either a DataTable or a DataSet.

The mechanism is very simple. Take a look at the following example, using a DataTable:

Dim adapter As New OleDbDataAdapter("Select * From Customers", _ connStr)
Dim dt As New DataTable()

' Import the query results into the DataTable
adapter.Fill(dt)

' Bind the DataTable to the DataGrid
DataGrid1.DataSource = dt

The DataSet works in almost exactly the same way:

Dim adapter As New OleDbDataAdapter("Select * From Customers", connStr)
Dim ds As New DataSet()

' Import the query results into the DataSet
adapter.Fill(ds)

' Bind a DataTable from the DataSet to the DataGrid
DataGrid1.DataSource = ds.Tables("Customers")

Notice in this example that instead of passing the entire DataSet to the DataGrid, weve chosen to bind only a single table. This is often necessary with controls for which multiple sets of tables dont make sense. The DataGrid is not one of these controls, however. It is capable of a multitable display (try it) and likes the DataSet just fine.

How to use DataView in Visual Basic .Net

0 comments

Posted on 7th June 2010 by reyman in Visual Basic .Net

, ,

A DataView is an object that allows you to create multiple views of your data and that can be used for data binding. The concept is fairly simple, but its importance cannot be overstated. The flexibility it introduces is impressive because a DataView does not actually change the DataTable from which it is generated. Instead, it offers a filtered window to the data. The following code shows how you can use the DataView control to filter rows based on a column value (in this case, the FirstName and LastName columns):

Function TestDataView()
   Dim adapter As New OleDbDataAdapter("Select * From Customers", _
   connStr)
   Dim ds As New DataSet()

   adapter.Fill(ds)

   Dim view1 As DataView = ds.Tables("Customers").DefaultView
   Dim view2 As DataView = ds.Tables("Customers").DefaultView

   view1.RowFilter = "'LastName' Like 'O%'"
   view2.RowFilter = "'FirstName' Like 'E%'"

   Dim i As Integer

   Debug.WriteLine("All LastNames starting with 'O'")
   For i = 0 To view1.Count - 1
      Debug.WriteLine(view1(i)("LastName"))
   Next

   Debug.WriteLine("All FirstNames starting with 'E'")
   For i = 0 To view2.Count - 1
      Debug.WriteLine(view1(i)("FirstName"))
   Next
End Function

Read and Write Text File in Visual Basic .Net

0 comments

Posted on 7th June 2010 by Kenneth in Visual Basic .Net

,

While were on the subject of the new file functions, lets take a short digression and quickly discuss how to write to and read from files using the new .NET Framework methods. You can still use the existing Visual Basic file functions, but the .NET Framework file methods, although a little more complicated, offer more flexibility when working with files.

Well create a simple console application that creates a file, writes Hello World to it, closes the file, and then reopens it and shows the contents in a message box.

Sub Main()
   '* Create a file and write to it
   Dim outFile As System.IO.FileStream
   outFile = New System.IO.FileStream("C:tempFile.txt", _
      IO.FileMode.Create, IO.FileAccess.Write)
   Dim fileWriter As New System.IO.StreamWriter(outFile)
   fileWriter.WriteLine("Hello World")
   fileWriter.Close()
   outFile.Close()

   '* Open a file and read from it
   Dim inFile As System.IO.FileStream
   inFile = New System.IO.FileStream("C:tempFile.txt", _
      IO.FileMode.Open, IO.FileAccess.Read)
   Dim fileReader As New System.IO.StreamReader(inFile)
   While fileReader.Peek > -1
      MsgBox(fileReader.ReadLine)
   End While
   fileReader.Close()
   inFile.Close()
 End Sub

To open a file for writing, you have to perform two steps: create a stream object and then create a StreamWriter object to write to the stream. You can then write to the file using the StreamWriter objects Write and WriteLine methods. Reading from a file involves a similar process: create a stream object, and then create a StreamReader to read from the stream. To determine whether there is anything to read from the file, use the StreamReader objects Peek method, which returns the value of the next byte in the file, or 1 if there is nothing left to read. The StreamReader objects Read, ReadBlock, ReadLine, and ReadToEnd methods are used to read the contents of the file.

How to Read the Contents of the Directory in Visual Basic .Net

0 comments

Posted on 7th June 2010 by reyman in Visual Basic .Net

,

In Visual Basic 6, it is awkward to read the contents of a directory: you have to call the Dir$ function repeatedly. This function returns the name of the first file in the directory, and then the next, and so on. You cant examine two directories at the same time because Dir$ tracks only the file it has enumerated for the current directory. In Visual Basic .NET, getting the list of files in a directory is much simpler. Use the System.IO.Directory.GetFiles method to return an array of filenames. The following sample code is from the Dashboard.GetSubForms method in the DynamicApp project:

Dim filePathArray() As String
filePathArray = System.IO.Directory.GetFiles(myDirectory(), "*.dll")

After this code runs, the filePathArray variable is filled with an array of file paths, such as

C:DynamicShellbinGraphicsFeatures.dll

The System.IO namespace contains many other useful functions as well. For example, System.IO.Path.GetDirectoryName returns the directory name from a file path. The code

MsgBox(System.IO.Path.GetDirectoryName( _
   "C:DynamicShellbinGraphicsFeatures.dll"))

shows C:DynamicShell in the message box. In a similar vein, the System.IO.Path.GetFileName method returns the filename of a file path. For example, the code

MsgBox(System.IO.Path.GetFileName( _
  "C:DynamicShellbinGraphicsFeatures.dll"))

shows GraphicsFeatures.dll in the message box. Another useful function is System.Reflection.Assembly.GetExecutingAssembly. This last method returns the file path of the application. DynamicApp passes the file path to System.IO.Path.GetDirectoryName to get the applications directory, which is how it knows where to look for DLLs.

Visual Basic 2002 – Making Your Code Thread-Safe

0 comments

Posted on 7th June 2010 by reyman in Visual Basic .Net

,

Threading issues may affect Visual Basic 6 ActiveX DLLs or UserControls that you upgrade to Visual Basic .NET, especially since the Visual Basic Upgrade Wizard does not make your code thread-safe when upgrading it. You will need to make manual changes to your codeas explained later in this sectionto make it thread-safe.

Such threading issues are uncommon, since components created in Visual Basic 6 are thread-safe by nature. Thread safety is accomplished in Visual Basic 6 by letting only a single thread access a component. Even if multiple threads are attempting to gain access to the component, all requests are synchronized through the single accessor thread associated with the component.

Visual Basic .NET components (including UserControls), on the other hand, are not thread-safe. Multiple threads are allowed to access the component simultaneously. There is no synchronization of threads on behalf of a Visual Basic .NET component. As a result, code that is thread-safe in Visual Basic 6 becomes unsafe after being upgraded to Visual Basic .NET. This change will affect you if you are running your component in a multithreaded environment such as Internet Explorer, Internet Information Services, or COM+. If you are not sure whether your component will be run in a multithreaded environment, it is always best to err on the side of caution and ensure that your component is thread-safe.

When more than one thread is executing your code, each thread has access to the same shared data: member variables and global variables. Allowing more than one thread to manipulate shared data at the same time can lead to problems. For example, if two threads are attempting to increment a count of items in a collection simultaneously, the count may be end up being incremented by 1 and not 2. This will happen if both threads obtain the current count at about the same time and add 1. Neither thread will see what the other thread is doing. We call this a synchronization problem, since it involves a situation in which only one thread at a time should be allowed to perform the operation.

For example, a synchronization problem can occur when one thread caches a global or member variable value in a local variable and performs a calculation on that variable. Lets take a look at the following Visual Basic .NET code.

Public Class GreedyBank

   Private m_Balance As Decimal

   Public Sub New()
      m_Balance = 20
   End Sub

   Public Function Withdraw(ByVal Amount As Decimal) As String

      'Protect against negative balance
      If m_Balance >= Amount Then
         m_Balance = m_Balance - Amount
      Else
         Return "The amount you requested will overdraw " & _
            "your account by $" & Amount  m_Balance
      End If

   End Function

End Class

This example is pretty straightforward. A client application calls Withdraw. Withdraw takes the current customer balance and deducts the requested withdrawal amount. To ensure that the customers account does not become overdrawn by the transaction, the function checks to make sure that the customer has enough money to cover the withdrawal amount.

This works great when only one thread at a time is executing the function. However, you can run into problems if two threads are executing the function simultaneously.

Lets suppose that the first thread has executed up to the following line:

m_Balance = m_Balance - Amount

The customers balance checked out, so the thread is ready to deduct the Amount. Assume that the customer has just enough money ($20) to cover the withdrawal request of $20. Just before the first thread executes the above statement, a second thread comes along, requesting an amount of $20 and completing the following statement:

        If m_Balance >= Amount Then

The second thread also sees that the bank balance, $20, is sufficient to cover the withdrawal request and proceeds to the next line:

m_Balance = m_Balance - Amount

At this point, the customer is rewarded with an account overdraft and the fees that accompany it. The first thread subtracts the withdrawal, leaving a balance of $0. The second thread, having successfully bypassed the sufficient-balance-to-cover-withdraw-amount check, then executes the same line, leaving a net balance of $20. Here code that on the surface appears to be perfectly legitimate leads to unanticipated resultsalthough the customer would need to submit two withdrawal requests simultaneously to encounter the problem.

Using a SyncLock Block

To fix this synchronization problem, you need to make sure that only one thread at a time has access to your shared member or global variables. In other words, you need to synchronize access to your data, letting only one thread at time execute certain blocks of code that manipulate shared data. You can do this by using the new Visual Basic .NET keyword SyncLock.

A SyncLock block ensures that only one thread at a time is executing code within the block. In the earlier code example, we can fix our negative balance problem by placing a SyncLock around the contents of the Withdraw function:

SyncLock GetType(GreedyBank)

   'Protect against negative balance
   If m_Balance >= Amount Then
      m_Balance = m_Balance - Amount
   Else
      Return "The amount you requested will overdraw " & _
         "your account by $" & Amount  m_Balance
   End If

End SyncLock

If there is any chance that your Visual Basic .NET component or UserControl will run in a multithreaded environment, we highly recommend using SyncLock blocks to protect your shared data. Taking the extra time to do this work up front can save you from grief down the road.