Tuesday, September 9, 2008

Windows Forms



Your Ad Here


The Microsoft .NET Framework includes a rich set of classes for creating traditional Windows-based applications in the System.Windows.Forms namespace. These range from basic controls such as the TextBox, Button, and MainMenu classes to specialized controls such as TreeView, LinkLabel, and NotifyIcon. In addition, you will find all the tools you need to manage Multiple Document Interface (MDI) applications, integrate context-sensitive help, and even create multilingual user interfaces— all without needing to resort to the complexities of the Win32 API. The traditional model for developing these Windows-based applications has not fundamentally changed since .NET was first released. The .NET Framework 3.0, initially released with Windows Vista, has made a formidable attempt to change the model with the introduction of Windows Presentation Foundation (WPF). WPF allows the development of highly sophisticated user interfaces using an enhanced design model that allows a much deeper control of all elements and their appearance. Furthermore, an attempt has been made to separate the user interface design from the code. Similar to how ASP .NET applications are designed, the front end (or user interface) for WPF applications is created using Extensible Application Markup Language (XAML, pronounced “zammel”). The back end is all handled by managed code. Visual Studio 2008 includes a detailed WPF designer that is similar to the Windows Forms designer. Other designers (Microsoft Expression Designer, Microsoft XAML Pad, and so on) that let you visually create XAML-based WPF applications are also available. It is important to note that WPF applications can be completely written in managed code rather than using XAML. This, however, goes against the underlying concept of WPF and would force you to create user interfaces without a designer (since they currently output only XAML). Since the topic of this book is Visual Basic (and not XAML), the in-depth subject of WPF and XAML is best handled by other sources such as the Pro WPF with VB 2008: Windows Presentation Foundation .NET 3.5 by Matthew MacDonald (Apress, 2008), Foundations of WPF: An Introduction to Windows Presentation Foundation by Laurence Moroney (Apress, 2006), or Applications = Code + Markup (Microsoft Press) by Charles Petzold. Therefore, this chapter will concentrate on tips and timesaving techniques to assist with building the more traditional Windows-based applications.
The following example demonstrates the dynamic creation of a list of checkboxes. One checkbox is
added for each item in a String array. All the checkboxes are added to a panel that has its AutoScroll
property set to True, which gives basic scrolling support to the checkbox list.
Imports System
Imports System.Windows.Forms
' All designed code is stored in the autogenerated partial
' class called Recipe09-01.Designer.vb. You can see this
' file by selecting Show All Files in Solution Explorer.
Partial Public Class Recipe09_01
Private Sub Recipe09_01_Load(ByVal sender As Object, ➥
ByVal e As System.EventArgs) Handles Me.Load
' Create an array of strings to use as the labels for
' the dynamic checkboxes.
Dim colors As String() = {"Red", "Green", "Black", "Blue", "Purple", ➥
"Pink", "Orange", "Cyan"}
' Suspend the panel's layout logic while multiple controls
' are added.
panel1.SuspendLayout()
' Specify the Y coordinate of the topmost checkbox in the list.
Dim topPosition As Integer = 10
' Create one new checkbox for each name in the list of colors
For Each color As String In colors
' Create a new checkbox.
Dim newCheckBox As New CheckBox
' Configure the new checkbox.
newCheckBox.Top = topPosition
newCheckBox.Left = 10
newCheckBox.Text = color
' Set the Y coordinate of the next checkbox.
topPosition += 30
' Add the checkbox to the panel contained by the form.
panel1.Controls.Add(newCheckBox)
Next
' Resume the form's layout logic now that all controls
' have been added.
Me.ResumeLayout()
End Sub
End Class


Language Integrated Query (LINQ)




Your Ad Here

Language Integrated Query (LINQ)

A key element of almost any application is data. Inevitably, data needs to be listed, sorted, analyzed, or displayed in some fashion. It is the nature of what we, as programmers, do. We accomplish this by manually performing the appropriate operations and relying on the current functionality provided by the existing .NET Framework. We also rely heavily on the use of external data sources, such as SQL Server or XML files. Before LINQ, writing code to query a data source required the query to be sent to the data source as a string where it would be executed. This resulted in a separation of functionality and control between the application and the data. The .NET Framework has always provided functionality (such as ADO.NET) that made things fairly painless, but it required that developers have intimate knowledge of the data source and its respective query language to be able to accomplish their goals. Most developers have become used to working with data in this manner and have adapted appropriately. Language Integrated Query (LINQ, pronounced “link”) has positioned itself to resolve this situation and is one of the major new additions to the .NET Framework 3.5. LINQ, at its core, is a set of features that, when used together, provide the ability to query any data source. Data can be easily queried and joined from multiple and varying data sources, such as joining data gathered from a SQL Server database and an XML file. The initial release of VB 9.0 includes several APIs that extend LINQ and provide support for the most common data sources, as listed in Table 6-1. LINQ was designed to be easily extended, which you can take advantage of to create full query support for any other data sources not covered by the included APIs.
LINQ to Objects, represented by the System.Linq namespace, extends the core LINQ framework and provides the mechanisms necessary to query data stored in objects that inherit IEnumerable(Of T). Querying IEnumerable objects is also supported but requires an extra step, which is covered in recipe 6-2. A standard query consists of one or more query operators that query the given data source and return the specified results. If you have any familiarity with Structured Query Language (SQL), which LINQ closely resembles, you will quickly recognize these standard operators. Here is an example query, assuming names is an IEnumerable(Of String):
Dim query = From name In names
This query uses the From clause, which designates the source of the data. This clause is structured
like a For...Next loop where you specify a variable to be used as the iterator (in the case, name)
and the source (in this case, names). As you can see by the example, you do not need to specify the data type for the iterator because it is inferred based on the data type of the source. It is possible to reference more than one data source in a single From clause, which would then allow you to query on each source or a combination of both (see recipe 6-11 for more details).
It is important to note that the previous example does not actually do anything. After that line
of code executes, query is an IEnumerable(Of T) that contains only information and instructions that
define the query. The query will not be executed until you actually iterate through the results. Most
queries work in this manner, but it is possible to force the query to execute immediately.
Like name, the data type for the results (query) is also being inferred. The data type depends on
what is being returned by the actual query. In this case, that would be an IEnumerable(Of String)
since name is a String. When creating queries, you are not required to use type inference. You could
have used the following:
Dim query As IEnumerable(Of String) = From name As String In names Select name
Although that would work, type inference makes the query appear much cleaner and easier to
follow. Since the example returns a sequence of values, you execute the query by iterating through it
using a For...Next loop, as shown here:
For Each name in query
...
Next
If you need to ensure that duplicate data in the source is not part of the results, then you can add
the Distinct clause to the end of your query. Any duplicate items in the source collection will be
skipped when the query is executed. If you did this to the previous example, it would look like this:
Dim query = From name In names Distinct
Both of the previous example queries use what is known as query syntax, which is distinguished
by the use of query clauses (such as From or Distinct). Query syntax is used primarily for appearance
and ease of use. When the code is compiled, however, this syntax is translated to and compiled as
method syntax.
Behind all query operators (clauses) is an actual method. The exception to this rule is the From
clause, which simply translates to the For...Next loop shown previously. These methods are actually
extension methods that extend IEnumberable(Of T) and are found in the System.Linq.Enumerable
class. The previous example would be compiled as this:
Dim query = names.Distinct
Query syntax is much easier to understand and appears cleaner in code, especially with longer
or more advanced queries. However, with some query operators, method syntax can give you more
fine-tuned control over the operation itself or the results.
The Code
The following example queries the array of Process objects returned from the Process.GetProcess
function and displays them to the console:
Imports System
Imports System.Linq
Imports System.Diagnostics
Namespace Apress.VisualBasicRecipes.Chapter06
Public Class Recipe06_01
Public Shared Sub Main()
' Build the query to return information for all
' processes running on the current machine. The
' data will be returned as instances of the Process
' class.
Dim procsQuery = From proc In Process.GetProcesses
' Run the query generated earlier and iterate
' through the results.
For Each proc In procsQuery
Console.WriteLine(proc.ProcessName)
Next
' Wait to continue.
Console.WriteLine()
Console.WriteLine("Main method complete. Press Enter.")
Console.ReadLine()
End Sub
End Class
End Namespace

Console Application



Your Ad Here

Create a Console Application from the Command Line

You need to use the VB .NET command-line compiler to build an application that does not require
a Windows graphical user interface (GUI) but instead displays output to, and reads input from, the
Windows command prompt (console).
In one of your classes, ensure you implement a Shared method named Main with one of the following
signatures:
Public Shared Sub Main()
End Sub
Public Shared Sub Main(ByVal args As String())
End Sub
Public Shared Function Main() As Integer
End Sub
Public Shared Function Main(ByVal args As String()) As Integer
End Sub
Build your application using the VB .NET compiler (vbc.exe) by running the following command
(where HelloWorld.vb is the name of your source code file):
vbc /target:exe HelloWorld.vb
By default, the VB .NET compiler will build a console application unless you specify otherwise. For
this reason, it’s not necessary to specify the /target:exe switch, but doing so makes your intention
clearer, which is useful if you are creating build scripts that will be used by others or will be used
repeatedly over a period of time.
To build a console application consisting of more than one source code file, you must specify all
the source files as arguments to the compiler. For example, the following command builds an application
named MyFirstApp.exe from two source files named HelloWorld.vb and ConsoleUtils.vb:
vbc /target:exe /main:HelloWorld /out:MyFirstApp.exe HelloWorld.vb ConsoleUtils.vb
The /out switch allows you to specify the name of the compiled assembly. Otherwise, the assembly
is named after the first source file listed—HelloWorld.vb in the example. If classes in both the HelloWorld
and ConsoleUtils files contain Main methods, the compiler cannot automatically determine which
method represents the correct entry point for the assembly. Therefore, you must use the compiler’s
/main switch to identify the name of the class that contains the correct entry point for your application.
When using the /main switch, you must provide the fully qualified class name (including the
namespace); otherwise, you will receive the following:
If you have a lot of VB .NET code source files to compile, you should use a response file. This
simple text file contains the command-line arguments for vbc.exe. When you call vbc.exe, you give
the name of this response file as a single parameter prefixed by the @ character. Here is an example:
vbc @commands.rsp
To achieve the equivalent of the previous example, commands.rsp would contain this:
/target:exe /main:HelloWorld /out:MyFirstApp.exe HelloWorld.vb ConsoleUtils.vb
For readability, response files can include comments (using the # character) and can span multiple
lines. The VB .NET compiler also allows you to specify multiple response files by providing multiple
parameters that are prefixed with the @ character.
The Code
The following code lists a class named ConsoleUtils that is defined in a file named ConsoleUtils.vb:
Imports System
Namespace Apress.VisualBasicRecipes.Chapter01
Public Class ConsoleUtils
' This method will display a prompt and read a response from the console.
Public Shared Function ReadString(ByVal message As String) As String
Console.Write(message)
Return Console.ReadLine
End Function
' This method will display a message on the console.
Public Shared Sub WriteString(ByVal message As String)
Console.WriteLine(message)
End Sub
' This method is used for testing ConsoleUtility methods.
' While it is not good practice to have multiple Main
' methods in an assembly, it sometimes can't be avoided.
' You specify in the compiler which Main sub routine should
' be used as the entry point. For this example, this Main
' routine will never be executed.
Public Shared Sub Main()
' Prompt the reader to enter a name.
Dim name As String = ReadString("Please enter a name: ")
' Welcome the reader to Visual Basic 2008 Recipes.
WriteString("Welcome to Visual Basic 2008 Recipes, " & name)
End Sub
End Class
End Namespace
The HelloWorld class listed next uses the ConsoleUtils class to display the message “Hello,
World” to the console (HelloWorld is contained in the HelloWorld.vb file):
Imports System
Namespace Apress.VisualBasicRecipes.Chapter01
Public Class HelloWorld
Public Shared Sub Main()
ConsoleUtils.WriteString("Hello, World")
ConsoleUtils.WriteString(vbCrLf & "Main method complete. Press Enter.")
Console.ReadLine()
End Sub
End Class
End Namespace
To build HelloWorld.exe from the two source files, use the following command:
vbc /target:exe /main:Apress.VisualBasicRecipes.Chapter01.HelloWorld ➥
/out:HelloWorld.exe ConsoleUtils.vb HelloWorld.vb