Appendix A. The Bottom Line

Each of The Bottom Line sections in the chapters suggest exercises to deepen skills and understanding. Sometimes there is only one possible solution, but often you are encouraged to use your skills and creativity to create something that builds on what you know and lets you explore one of many possible solutions.

Chapter 1: Getting Started with Visual Basic 2010

Navigate the integrated development environment of Visual Studio.

To simplify the process of application development, Visual Studio provides an environment that's common to all languages, known as an integrated development environment (IDE). The purpose of the IDE is to enable the developer to do as much as possible with visual tools before writing code. The IDE provides tools for designing, executing, and debugging your applications. It's your second desktop, and you'll be spending most of your productive hours in this environment.

Master It

Describe the basic components of the Visual Studio IDE.

Solution

The basic components of the Visual Studio IDE are the Form Designer, where you design the form by dropping and arranging controls, and the code editor, where you write the code of the application. The controls you can place on the form to design the application's interface are contained in the Toolbox window. To set the properties of a control, you must select it on the form and locate the appropriate property in the Properties window.

Understand the basics of a Windows application.

A Windows application consists of a visual interface and code. The visual interface is what users see at runtime: a form with controls with which the user can interact — by entering strings, checking or clearing check boxes, clicking buttons, and so on. The visual interface of the application is designed with visual tools. The visual elements incorporate a lot of functionality, but you need to write some code to react to user actions.

Master It

Describe the process of building a simple Windows application.

Solution

First, you must design the form of the application by dropping controls from the Toolbox window onto the form. Size and align the controls on the form, and then set their properties in the Properties window. The controls include quite a bit of functionality right out of the box. A TextBox control with its MultiLine property set to True and its ScrollBars property set to Vertical is a complete, self-contained text editor.

After the visual interface has been designed, you can start coding the application. Windows applications follow an event-driven model: Code the events to which you want your application to react. The Click events of the various buttons are typical events to which an application reacts.

Then, there are events that are ignored by developers. The TextBox control, for example, fires some 60 events, but most applications don't react to more than one or two of them. Select the actions to which you want your application to react and program these events accordingly. When an event is fired, the appropriate event handler is automatically invoked.

Event handlers are subroutines that pass two arguments to the application: the sender argument, which is the control that fired the event, and the e argument which carries additional information about the event (information such as the mouse button that was pressed, the character typed by the user, and so on). To program a specific event for a control, double-click the control on the design surface and the editor window will come up with the default event for the control. You can select any other event for the same control to program in the Events combo box at the top of the editor's window.

Chapter 2: Handling Data

Declare and use variables.

Programs use variables to store information during their execution, and different types of information are stored in variables of different types. Dates, for example, are stored in variables of the Date type, while text is stored in variables of the String type. The various data types expose a lot of functionality that's specific to a data type; the methods provided by each data type are listed in the IntelliSense box.

Master It

How would you declare and initialize a few variables?

Solution

To declare multiple variables in a single statement, append each variable's name and type to the Dim statement.

Dim speed As Single, distance As Integer

Variables of the same type can be separated with commas, and you need not repeat the type of each variable:

Dim First, Last As String, BirthDate As Date

To initialize the variables, append the equals sign and the value as shown here:

Dim speed As Single = 75.5, distance As Integer = 14902
Master It

Explain briefly the Explicit, Strict, and Infer options.

Solution

These three options determine how Visual Basic handles variable types, and they can be turned on or off. The Explicit option requires that you declare all variables in your code before using them. When it's off, you can use a variable in your code without declaring it. The compiler will create a new variable of the Object type. The Strict option requires that you declare variables with a specific type. If the Strict option if off, you can declare variables without a type, with a statement like this:

Dim var1, var2

The last option, Infer, allows you to declare and initialize typed variables without specifying their type. The compiler infers the variable's type from the value assigned to it. The following declarations will create a String and a Date variable as long as the Infer option is on. Otherwise, they will create two object variables:

Dim D = #3/5/1008#, S="my name"
Use the native data types.

The CLR recognized the following data types, which you can use in your code to declare variables: String, numeric data types (Integer, Double, and so on), Date, Char and Boolean types.

All other variables, or variables that are declared without a type, are Object variables and can store any data type or any object.

Master It

How will the compiler treat the following statement?

Dim amount = 32
Solution

The amount variable is not declared with a specific data type. With the default settings, the compiler will create a new Object variable and store the value 32 in it. If the Infer option is on, the compiler will create an Integer variable and store the value 32 in it. If you want to be able to store amounts with a fractional part in this variable, you must assign a floating-point value to the variable (such as 32.00) or append the R type character to the value (32R).

Create custom data types.

Practical applications need to store and manipulate multiple data items, not just integers and strings. To maintain information about people, we need to store each person's name, date of birth, address, and so on. Products have a name, a description, a price, and other related items. To represent such entities in our code, we use structures, which hold many pieces of information about a specific entity together.

Master It

Create a structure for storing products and populate it with data.

Solution

Structures are declared with the Structure keyword and their fields with the Dim statement:

Structure Product
    Dim ProductCode As String
    Dim ProductName As String
    Dim Price As Decimal
    Dim Stock As Integer
End Structure

To represent a specific product, declare a variable of the Product type and set its fields, which are exposed as properties of the variable:

Dim P1 As Product
P1.ProductCode = "SR-0010"
P1.ProductName = "NTR TV-42"
P1.Price = 374.99
P1.Stock = 3
Use arrays.

Arrays are structures for storing sets of data as opposed to single-valued variables.

Master It

How would you declare an array for storing 12 names and another one for storing 100 names and Social Security numbers?

Solution

The first array stores a set of single-valued data (names) and it has a single dimension. Since the indexing of the array's elements starts at 0, the last element's index for the first array is 11, and it must be declared as follows:

Dim Names(11) As String

The second array stores a set of pair values (names and SSNs), and it must be declared as a two-dimensional array:

Dim Persons(100,1) As String

If you'd rather avoid the index 0, you can declare the two arrays as follows:

Dim Names(1 To 11) As String
Dim Persons(1 To 100, 1 To 1) As String

Chapter 3: Visual Basic Programming Essentials

Use Visual Basic's flow-control statements.

Visual Basic provides several statements for controlling the flow of control in a program: decision statements, which change the course of execution based on the outcome of a comparison, and loop statements, which repeat a number of statements while a condition is true or false.

Master It

Explain briefly the decision statements of Visual Basic.

Solution

The basic decision statement in VB is the If...End If statement, which executes the statements between the If and End If keywords if the condition specified in the If part is true. A variation of this statement is the If...Then...Else statement.

If the same expression must be compared to multiple values and the program should execute different statements depending on the outcome of the comparison, use the Select Case statement.

Write subroutines and functions.

To manage large applications, break your code into small, manageable units. These units of code are the subroutines and functions. Subroutines perform actions and don't return any values. Functions, on the other hand, perform calculations and return values. Most of the language's built-in functionality is in the form of functions.

Master It

How will you create multiple overloaded forms of the same function?

Solution

Overloaded functions are variations on the same function with different arguments. All overloaded forms of a function have the same name, and they're prefixed with the Overloads keyword. Their lists of arguments, however, are different — either in the number of arguments or in the argument types.

Pass arguments to subroutines and functions.

Procedures and functions communicate with one another via arguments, which are listed in a pair of parentheses following the procedure's name. Each argument has a name and a type. When you call a procedure, you must supply values for each argument, and the types of the values should match the types listed in the procedure's definition.

Master It

Explain the difference between passing arguments by value and passing arguments by reference.

Solution

The first mechanism, which was the default mechanism with earlier versions of the language, passes a reference to the argument. Arguments passed by reference are prefixed by the keyword ByRef in the procedure's definition. The procedure has access to the original values of the arguments passed by reference and can modify them. The second mechanism passes to the procedure a copy of the original value. Arguments passed by value are prefixed with the keyword ByVal in the procedure's definition. The procedure may change the values of the arguments passed by value, but the changes won't affect the value of the original variable.

Chapter 4: GUI Design and Event-Driven Programming

Design graphical user interfaces.

A Windows application consists of a graphical user interface and code. The interface of the application is designed with visual tools and consists of controls that are common to all Windows applications. You drop controls from the Toolbox window onto the form, size and align the controls on the form, and finally set their properties through the Properties window. The controls include quite a bit of functionality right out of the box, and this functionality is readily available to your application without a single line of code.

Master It

Describe the process of aligning controls on a form.

Solution

To align controls on a form, you should select them in groups, according to their alignment. Controls can be aligned to the left, right, top, and bottom. After selecting a group of controls with a common alignment, apply the proper alignment with one of the commands of the Format

Chapter 4: GUI Design and Event-Driven Programming
Program events.

Windows applications follow an event-driven model: We code the events to which we want our application to respond. For example, an application reacts to Click events of the various buttons. You select the actions to which you want your application to react and program these events accordingly.

When an event is fired, the appropriate event handler is automatically invoked. Event handlers are subroutines that pass two arguments to the application: the sender argument (which is an object that represents the control that fired the event) and the e argument (which carries additional information about the event).

Master It

How will you handle certain keystrokes regardless of the control that receives them?

Solution

You can intercept all keystrokes at the form's level by setting the form's KeyPreview property to True. Then insert some code in the form's KeyPress event handler to examine the keystroke passed to the event handler and to process it. To detect the key presses in the KeyPress event handler, use an If statement like the following:

If e.KeyChar = "A" Then
'   process the A key
End If
Write robust applications with error handling.

Numerous conditions can cause an application to crash, but a well-written application should be able to detect abnormal conditions and handle them gracefully. To begin with, you should always validate your data before you attempt to use them in your code. A well-known computer term is "garbage in, garbage out," which means you shouldn't perform any calculations on invalid data.

Master It

How will you execute one or more statements in the context of a structured exception handler?

Solution

A structured exception handler has the following syntax:

Try
  ' {statements}
Catch ex As Exception
  ' {statements to handle exception}
Finally
  ' {clean-up statements}
End Try

The statements you want to execute must be inserted in the Try block of the statement. If the statements are executed successfully, program execution continues with the statements following the End Try statement. If an error occurs, the Catch block is activated, where you can display the appropriate message and take the proper actions. At the very least, you should save the user data and then terminate the application. In many cases, it's even possible to remedy the situation that caused the exception in the first place. No matter what the Try block execution outcome (error or no error) is, the Finally block is executed, making it a convenient location for release and cleanup of reserved resources.

Chapter 5: Basic Windows Controls

Use the TextBox control as a data-entry and text-editing tool.

The TextBox control is the most common element of the Windows interface, short of the Button control, and it's used to display and edit text. You can use a TextBox control to prompt users for a single line of text (such as a product name) or a small document (a product's detailed description). You can actually implement a functional text editor by placing a TextBox control on a form and setting a few of its properties.

Master It

What are the most important properties of the TextBox control? Which ones would you set in the Properties windows at design time?

Solution

The first property you'll most likely change is the MultiLine property, whose default value is False. To set the initial text on the control, use the Text or Lines properties. The Text property returns or sets the text on the control. The Lines property is an array of string that holds each text line in a separate element. To interact with the user, use the text-selection properties SelectedText, SelectionLength, and SelectionStart. You can use these properties to retrieve and manipulate the text selected by the user on the control or to select text from within your code.

Master It

How would you implement a control that suggests lists of words matching the characters entered by the user?

Solution

Use the autocomplete properties AutoCompleteMode, AutoCompleteSource, and AutoCompleteCustomSource. The AutoCompleteMode property determines whether the control will suggest the possible strings, automatically complete the current word as you type, or do both. The AutoCompleteSource property specifies where the strings that will be displayed will come from and its value is a member of the AutoCompleteSource enumeration. If this property is set to AutoCompleteSoure.CustomSource, you must set up an AutoCompleteStringCollection collection with your custom strings and assign it to the AutoCompleteCustomSource property.

Use the ListBox, CheckedListBox, and ComboBox controls to present lists of items.

The ListBox control contains a list of items from which the user can select one or more, depending on the setting of the SelectionMode property.

Master It

How would you locate an item in a ListBox control?

Solution

To locate a string in a ListBox control, use the FindString and FindStringExact methods. The FindString method locates a string that partially matches the one you're searching for; FindStringExact finds an exact match. Both methods perform case-insensitive searches and return the index of the item they've located in the list.

We usually call the FindStringExact method and then examine its return value. If an exact match is found, we select the item with the index returned by the FindExact method. If an exact match is not found, in which case the method returns −1, we call the FindString method to locate the nearest match.

Use the ScrollBar and TrackBar controls to enable users to specify sizes and positions with the mouse.

The ScrollBar and TrackBar controls let the user specify a magnitude by scrolling a selector between its minimum and maximum values. The ScrollBar control uses some visual feedback to display the effects of scrolling on another entity, such as the current view in a long document.

Master It

Which event of the ScrollBar control would you code to provide visual feedback to the user?

Solution

The ScrollBar control fires two events: the Scroll event and the ValueChanged event. They're very similar and you can program either event to react to the changes in the ScrollBar control. The advantage of the Scroll event is that it reports the action that caused it through the e.Type property. You can examine the value of this property in your code and react to actions like the end of the scroll:

Private Sub blueBar_Scroll(
ByVal sender As System.Object,
ByVal e As System.Windows.Forms.ScrollEventArgs)
Handles blueBar.Scroll
    If e.Type = ScrollEventType.EndScroll Then
    ' perform calculations and provide feedback
    End If
End Sub

Chapter 6: Working with Forms

Visual form design

Forms expose a lot of trivial properties for setting their appearance. In addition, they expose a few properties that simplify the task of designing forms that can be resized at runtime. The Anchor property causes a control to be anchored to one or more edges of the form to which it belongs. The Dock property allows you to place on the form controls that are docked to one of its edges. To create forms with multiple panes that the user can resize at runtime, use the SplitContainer control. If you just can't fit all the controls in a reasonably sized form, use the AutoScroll properties to create a scrollable form.

Master It

You've been asked to design a form with three distinct sections. You should also allow users to resize each section. How will you design this form?

Solution

The type of form required is easily designed with visual tools and the help of the SplitContainer control. Place a SplitContainer control on the form and set its Dock property to Fill. You've just created two vertical panes on the form, and users can change their relative sizes at any time. To create a third pane, place another SplitContainer control on one of the first control's panes and set its Dock property to Fill and its Orientation property to Horizontal. At this point, the form is covered by three panes and users can change each pane's size at the expense of its neighboring panes.

Design applications with multiple forms.

Typical applications are made up of multiple forms: the main form and one or more auxiliary forms. To show an auxiliary form from within the main form's code, call the auxiliary form's Show method, or the ShowDialog method if you want to display the auxiliary form modally (as a dialog box).

Master It

How will you set the values of selected controls in a dialog box, display them, and then read the values selected by the user from the dialog box?

Solution

Create a Form variable that represents the dialog box and then access any control on the dialog box through its name as usual, prefixed by the form's name:

Dim Dlg As AuxForm
Dlg.txtName = "name"

Then call the form's ShowDialog method to display it modally and examine the DialogResult property returned by the method. If this value is OK, process the data on the dialog box; if it isn't, do not process the dialog box:

If Dlg.ShowDialog = DialogResult.OK Then
    UserName = Dlg.TxtName
End If

To display an auxiliary form, just call the Show method. This method doesn't return a value, and you can read the auxiliary form's contents from within the main form's code at any time. You can also access the controls of the main form from within the auxiliary form's code.

Design dynamic forms.

You can create dynamic forms by populating them with controls at runtime through the form's Controls collection. First, create instances of the appropriate controls by declaring variables of the corresponding type. Then set the properties of each of these variables that represent controls. Finally, place the control on the form by adding the corresponding variable to the form's Controls collection.

Master It

How will you add a TextBox control to your form at runtime and assign a handler to the control's TextChanged event?

Solution

Create an instance of the TextBox control, set its Visible property and then add it to the form's Controls collection:

Dim TB As New TextBox
TB.Visible = True
' statements to set other properties,
' including the control's location on the form
Me.Controls.Add(TB)

Then write a subroutine that will handle the TextChanged event. This subroutine, let's call it TBChanged(), should have the same signature as the TextBox control's TextChanged event. Use the AddHandler statement to associate the TBChanged() subroutine with the new control's TextChanged event:

AddHandler TB.TextChanged, _
     New SystemEventHandler(AddressOf TBChanged)
Design menus.

Both form menus and context menus are implemented through the MenuStrip control. The items that make up the menu are ToolStripMenuItem objects. The ToolStripMenuItem objects give you absolute control over the structure and appearance of the menus of your application.

Master It

What are the two basic events fired by the ToolStripMenuItem object?

Solution

When the user clicks a menu item, the DropDownOpened and Click events are fired in this order. The DropDownOpened event gives you a chance to modify the menu that's about to be opened. After the execution of the DropDownOpened event handler, the Click event takes place to indicate the selection of a menu command. We rarely program the DropDownOpened event, but every menu item's Click event handler should contain some code to react to the selection of the item.

Chapter 7: More Windows Controls

Use the OpenFileDialog and SaveFileDialog controls to prompt users for filenames.

Windows applications use certain controls to prompt users for common information, such as filenames, colors, and fonts. Visual Studio provides a set of controls that are grouped in the Dialogs section of the Toolbox. All common dialog controls provide a ShowDialog method, which displays the corresponding dialog box in a modal way. The ShowDialog method returns a value of the DialogResult type, which indicates how the dialog box was closed, and you should examine this value before processing the data.

Master It

Your application needs to open an existing file. How will you prompt users for the file's name?

Solution

First you must drop an instance of the OpenFileDialog control on the form. To limit the files displayed in the Open dialog box, use the Filter property to specify the relevant file type(s). To display text files only, set the Filter property to Text files|*.txt. If you want to display multiple filename extensions, use a semicolon to separate extensions with the Filter property; for example, the string Images|*.BMP;*.GIF;*.JPG will cause the control to select all the files of these three types and no others. The first part of the expression (Images) is the string that will appear in the drop-down list with the file types. You should also set the CheckFileExists property to True to make sure the file specified on the control exists. Then display the Open dialog box by calling its ShowDialog method, as shown here:

If FileOpenDialog1.ShowDialog =
      Windows.Forms.DialogResult.OK
       {process file FileOpenDialog1.FileName}
End If

To retrieve the selected file, use the control's FileName property, which is a string with the selected file's path.

Master It

You're developing an application that encrypts multiple files (or resizes many images) in batch mode. How will you prompt the user for the files to be processed?

Solution

There are two techniques to prompt users for multiple filenames. Both techniques, however, are limited in the sense that all files must reside in the same folder. The first technique is to set the MultiSelect property of the OpenFileDialog control to True. Users will be able to select multiple files by using the Ctrl and Shift keys. The selected files will be reported to your application through the FileNames property of the control, which is an array of strings.

OpenFileDialog1.Multiselect = True
OpenFileDialog1.ShowDialog()
Dim filesEnum As IEnumerator
ListBox1.Items.Clear()
filesEnum =
OpenFileDialog1.FileNames.GetEnumerator()
While filesEnum.MoveNext
    ' current file's name is filesEnum.Current
End While

The other technique is to use the FolderBrowserDialog control, which prompts users to select a folder, not individual files. Upon return, the control's SelectedPath property contains the pathname of the folder selected by the user from the dialog box, and you can use this property to process all files of a specific type in the selected folder.

Use the ColorDialog and FontDialog controls to prompt users for colors and typefaces.

The Color and Font dialog boxes allow you to prompt users for a color value and a font, respectively. Before showing the corresponding dialog box, set its Color or Font property according to the current selection, and then call the control's ShowDialog method.

Master It

How will you display color attributes in the Color dialog box when you open it? How will you display the attributes of the selected text's font in the Font dialog box when you open it?

Solution

To prompt users to specify a different color for the text on a TextBox control, execute the following statements:

ColorDialog1.Color = TextBox1.ForeColor
If ColorDialog1.ShowDialog = DialogResult.OK Then
    TextBox1.ForeColor = ColorDialog1.Color
End If

To populate the Font dialog box with the font in effect, assign the TextBox control's Font property to the FontDialog control's Font property by using the following statements:

FontDialog1.Font = TextBox1.Font
If FontDialog1.ShowDialog = DialogResult.OK Then
    TextBox1.Font = FontDialog1.Font
End If
Use the RichTextBox control as an advanced text editor to present richly formatted text.

The RichTextBox control is an enhanced TextBox control that can display multiple fonts and styles, format paragraphs with different styles, and provide a few more-advanced text-editing features. Even if you don't need the formatting features of this control, you can use it as an alternative to the TextBox control. At the very least, the RichTextBox control provides more editing features, a more-useful undo function, and more-flexible search features.

Master It

You want to display a document with a title in large, bold type, followed by a couple of items in regular style. Which statements will you use to create a document like this on a RichTextBox control?

Document's Title

Item 1

Description for item 1

Item 2

Description for item 2

Solution

To append text to a RichTextBox control, use the AppendText method. This method accepts a string as an argument and appends it to the control's contents. The text is formatted according to the current selection's font, which you must set accordingly through the SelectionFont property. To switch to a different font, set the SelectionFont property again and call the AppendText method.

Assuming that the form contains a control named RichTextBox1, the following statements will create a document with multiple formats. In this sample, I'm using three different typefaces for the document.

Dim fntTitle As
        New Font("Verdana", 12, FontStyle.Bold)
Dim fntItem As
        New Font("Verdana", 10, FontStyle.Bold)
Dim fntText As
        New Font("Verdana", 9, FontStyle.Regular)
Editor.SelectionFont = fntTitle
Editor.AppendText("Document's Title" & vbCrLf)
Editor.SelectionFont = fntItem
Editor.SelectionIndent = 20
Editor.AppendText("Item 1" & vbCrLf)
Editor.SelectionFont = fntText
Editor.SelectionIndent = 40
Editor.AppendText(
              "Description for item 1" & vbCrLf)
Editor.SelectionFont = fntItem
Editor.SelectionIndent = 20
Editor.AppendText("Item 2" & vbCrLf)
Editor.SelectionFont = fntText
Editor.SelectionIndent = 40
Editor.AppendText(
              "Description for item 2" & vbCrLf)
Create and present hierarchical lists by using the TreeView control.

The TreeView control is used to display a list of hierarchically structured items. Each item in the TreeView control is represented by a TreeNode object. To access the nodes of the TreeView control, use the TreeView.Nodes collection. The nodes under a specific node (in other words, the child nodes) form another collection of Node objects, which you can access by using the expression TreeView.Nodes(i).Nodes. The basic property of the Node object is the Text property, which stores the node's caption. The Node object exposes properties for manipulating its appearance (its foreground/background color, its font, and so on).

Master It

How will you set up a TreeView control with a book's contents at design time?

Solution

Place an instance of the TreeView control on the form and then locate its Nodes property in the Properties window. Click the ellipsis button to open the TreeNode Editor dialog box, where you can enter root nodes by clicking the Add Root button and child nodes under the currently selected node by clicking the Add Child button. The book's chapters should be the control's root nodes, and the sections should be child nodes of those chapter nodes. If you have nested sections, add them as child nodes of the appropriate node. While a node is selected in the left pane of the dialog box, you can specify its appearance in the right pane by setting the font, color, and image-related properties.

Create and present lists of structured items by using the ListView control.

The ListView control stores a collection of ListViewItem objects, which forms the Items collection, and can display them in several modes, as specified by the View property. Each ListViewItem object has a Text property and the SubItems collection. The subitems are not visible at runtime unless you set the control's View property to Details and set up the control's Columns collection. There must be a column for each subitem you want to display on the control.

Master It

How will you set up a ListView control with three columns to display names, email addresses, and phone numbers at design time?

Solution

Drop an instance of the ListView control on the form and set its View property to Details. Then locate the control's Columns property in the Properties window and add three columns to the collection through the ColumnHeader Collection Editor dialog box. Don't forget to set their headers and their widths for the fields they will display.

To populate the control at design time, locate its Items property in the Properties window and click the ellipsis button to open the ListViewItem Collection Editor dialog box. Add a new item by clicking the Add button. When the new item is added to the list in the left pane of the dialog box, set its Text property to the desired caption. To add subitems to this item, locate the SubItems property in the ListViewItem Collection Editor dialog box and click the ellipsis button next to its value. This will open another dialog box, the ListViewSubItems Collection Editor dialog box, where you can add as many subitems under the current item as you wish. You can also set the appearance of the subitems (their font and color) in the same dialog box.

Master It

How would you populate the same control with the same data at runtime?

Solution

The following code segment adds two items to the ListView1 control at runtime:

Dim LItem As New ListViewItem()
LItem.Text = "Alfred's Futterkiste"
LItem.SubItems.Add("Anders Maria")
LItem.SubItems.Add("030-0074321")
LItem.SubItems.Add("030-0076545")
LItem.ImageIndex = 0
ListView1.Items.Add(LItem)

LItem = New ListViewItem()
LItem.Text = "Around the Horn"
LItem.SubItems.Add("Hardy Thomas")
LItem.SubItems.Add(" (171) 555-7788")
LItem.SubItems.Add("171) 555-6750")
LItem.ImageIndex = 0
ListView1.Items.Add(LItem)

Chapter 8: Working with Projects

Build your own classes.

Classes contain code that executes without interacting with the user. The class's code is made up of three distinct segments: the declaration of the private variables, the property procedures that set or read the values of the private variables, and the methods, which are implemented as public subroutines or functions. Only the public entities (properties and methods) are accessible by any code outside the class. Optionally, you can implement events that are fired from within the class's code. Classes are referenced through variables of the appropriate type, and applications call the members of the class through these variables. Every time a method is called, or a property is set or read, the corresponding code in the class is executed.

Master It

How do you implement properties and methods in a custom class?

Solution

Any variable declared with the Public access modifier is automatically a property. As a class developer, however, you should be able to validate any values assigned to your class's properties. To do so, you can implement properties with a special type of procedure, the property procedure, which has two distinct segments: a Set segment that's invoked when an application attempts to set a property and the Get segment, invoked when an application attempts to read a property's value. The property has the following structure:

Private m_property As type
Property Property() As type
   Get
      Property = m_property
   End Get
   Set (ByVal value As type)
   ' your validation code goes here
   ' If validation succeeds, set the local var
      m_property = value
   End Set
End Property

The local variable m_property must be declared with the same type as the property. The Get segment returns the value of the local variable that stores the property's value. The Set segment validates the value passed by the calling application and either rejects it or sets the local variable to this value.

Master It

How would you use a constructor to allow developers to create an instance of your class and populate it with initial data?

Solution

Each class has a constructor, which is called every time a new instance of the class is created with the New keyword. The constructor is implemented with the New() subroutine. To allow users to set certain properties of the class when they instantiate it, create as many New() subroutines as you need. Each version of the New() subroutine should accept different arguments. The following sample lets you create objects that represent books, passing a book's ISBN and/or title:

Public Sub New(ByVal ISBN As String)
    MyBase.New()
    Me.ISBN = ISBN
End Sub

Public Sub New(ByVal ISBN As String, ByVal Title As String)
    MyBase.New()
Me.ISBN = ISBN
    Me.Title = Title
End Sub

This technique bypasses the New constructor, but the appropriate Property procedures are invoked, as each property is initialized.

Master It

Which are the default methods of a custom class that you will most likely override with more meaningful definitions?

Solution

The first method to override is the ToString method, which returns a string that describes the class. By default, this method returns the name of the class. Your implementation should return a more meaningful string. The Equals method, which compares two instances of the same class, is another candidate for overriding because the default Equals method performs a reference comparison, not an instance comparison.

To override one of the default methods, enter the string

Public Overrides

in the code window and press the spacebar to see the signatures of the overridable methods in the IntelliSense drop-down box.

Master It

How should you handle exceptions in a class?

Solution

In general, you should avoid handling all errors in your class because you can't be sure how your classes will be used by other developers. It's also important that you avoid interacting with the user from within your class's code with messages boxes or other techniques. The best method of handling errors in a custom class is to raise exceptions and let the developer of the calling application handle the errors.

Overloading operators.

Overloading is a common theme in coding classes (or plain procedures) with Visual Basic. In addition to overloading methods, you can overload operators. In other words, you can define the rules for adding or subtracting two custom objects, if this makes sense for your application.

Master It

When should you overload operators in a custom class, and why?

Solution

It may make absolute sense to add two instances of a custom class (it may represent length, matrices, vectors, and so on), but the addition operator doesn't work with custom classes. To redefine the addition operator so that it will add two instances of your custom class, you must override the addition operator with an implementation that adds two instances of a custom class. The following is the signature of a function that overloads the addition operator:

Public Shared Operator + (
            ByVal object1 As customType,
            ByVal object2 As customType)
            As customType

    Dim result As New customType
    ' Insert the code to "add" the two
' arguments and store the result to
    ' the result variable and return it.
    Return result
End Operator

The function that overrides the addition operator accepts two arguments, which are the two values to be added, and returns a value of the same type. The operator is usually overloaded because you may wish to add an instance of the custom class to one of the built-in data types or objects.

Chapter 9: Building Custom Windows Controls

Extend the functionality of existing Windows Forms controls with inheritance.

The simplest type of control you can build is one that inherits an existing control. The inherited control includes all the functionality of the original control plus some extra functionality that's specific to an application and that you implement with custom code.

Master It

Describe the process of designing an inherited custom control.

Solution

To enhance an existing Windows Forms control, insert an Inherits statement with the name of the control you want to enhance in the project's Designer.vb file. The inherited control interface can't be altered; it's determined by the parent control. However, you can implement custom properties and methods, react to events received by the parent control, or raise custom events from within your new control.

The process of implementing custom properties and methods is identical to building custom classes. The control's properties, however, can be prefixed by a number of useful attributes, like the <Category> and <Description> attributes, which determine the category of the Properties Browser where the property will appear and the control's description that will be shown in the Properties window when the custom property is selected.

Build compound controls that combine multiple existing controls.

A compound control provides a visible interface that combines multiple Windows controls. As a result, this type of control doesn't inherit the functionality of any specific control; you must expose its properties by providing your own code. The UserControl object, on which the compound control is based, already exposes a large number of members, including some fairly advanced ones such as the Anchoring and Docking properties, and the usual mouse and key events.

Master It

How will you map certain members of a constituent control to custom members of the compound control?

Solution

If the member is a property, you simply return the constituent control's property value in the Get section of the Property procedure and set the constituent control's property to the specified value in the Set section of the same procedure. The following Property procedure maps the WordWrap property of the TextBox1 constituent control to the TextWrap property of the custom compound control:

Public Property TextWrap() As Boolean
    Get
        Return TextBox1.WordWrap
End Get
    Set(ByVal value As Boolean)
        TextBox1.WordWrap = value
    End Set
End Property

If the member is a method, you just call it from within one of the compound control's methods. To map the ResetText method of the TextBox constituent control to the Reset method of the compound control, add the following method definition:

Public Sub Reset()
    TextBox1.ResetText
End Sub

In the UserControl object's Load event handler, insert the statements that create the roundPath object, which is an ellipse, and then assign it to the UserControl's Region property. Here's the Load event handler for the EllipticalButton custom control:

Private Sub RoundButton_Load(ByVal sender As System.Object,
                ByVal e As System.EventArgs)
                Handles MyBase.Load
   Dim G As Graphics
   G = Me.CreateGraphics
   Dim roundPath As New GraphicsPath()
   Dim R As New Rectangle(0, 0, Me.Width, Me.Height)
   roundPath.AddEllipse(R)
   Me.Region = New Region(roundPath)
End Sub
Build custom controls from scratch.

User-drawn controls are the most flexible custom controls because you're in charge of the control's functionality and appearance. Of course, you have to implement all the functionality of the control from within your code, so it takes substantial programming effort to create user-drawn custom controls.

Master It

Describe the process of developing a user-drawn custom control.

Solution

Since you are responsible for updating the control's visible area from within your code, you must provide the code that redraws the control's surface and insert it in the UserControl object's Paint event handler. In drawing the control's surface, you must take into consideration the settings of the control's properties.

Private Sub Label3D_Paint(
         ByVal sender As Object,
         ByVal e As System.Windows.Forms.PaintEventArgs)
          Handles Me.Paint

End Sub

The e argument of the Paint event handler exposes the Graphics property, which you must use from within your code to draw on the control's surface. You can use any of the drawing methods you'd use to create shapes, gradients, and text on a Form object or PictureBox control.

Because custom controls aren't redrawn by default when they're resized, you must also insert the following statement in the control's Load event handler:

Private Sub Label3D_Load(
             ByVal sender As System.Object,
             ByVal e As System.EventArgs)
             Handles MyBase.Load
    Me.SetStyle(ControlStyles.ResizeRedraw, True)
End Sub

If the control's appearance should be different at design time than at runtime, use the Me.DesignMode property to determine whether the custom control is used in design time (DesignMode = True), or runtime (DesignMode = False).

Customize the rendering of items in a ListBox control.

The Windows controls that present lists of items display their items in a specific manner. The Framework allows you to take control of the rendering process and change completely the default appearance of the items on these controls. The controls that allow you to take charge of the rendering process of their items are the ListBox, CheckedListBox, ComboBox, and TreeView controls.

To create an owner-drawn control, you must set the DrawMode property to a member of the DrawMode enumeration and insert the appropriate code in the events MeasureItem and DrawItem. The MeasureItem event is where you decide about the dimensions of the rectangle in which the drawing will take place. The DrawItem event is where you insert the code for rendering the items on the control.

Master It

Outline the process of creating a ListBox control that wraps the contents of lengthy items.

Solution

By default, all items in a ListBox control have the same height, which is the height of a single line of text in the control's font. To display the selected items in cells of varying height, do the following:

  1. Set the control's DrawMode property to OwnerDrawVariable.

  2. In the control's MeasureItem event handler, which is invoked every time the control is about to display an item, insert the statements that calculate the desired height of the current item's cell. You will most likely call the MeasureString method of the control's Graphics object to retrieve the height of the item (the item may take multiple lines on the control). Set the e.Height and e.Width properties before exiting the MeasureItem event handler.

  3. In the control's DrawItem event handler, which displays the current item, insert the appropriate statements to print the item in a cell with the dimensions calculated in step 2. The dimensions of the cell in which you must fit the caption of the current item are given by the property Bounds of the event handler's e argument. Use the DrawString method of the control's Graphics object to draw the item's caption.

Chapter 10: Applied Object-Oriented Programming

Use inheritance.

Inheritance, which is the true power behind OOP, allows you to create new classes that encapsulate the functionality of existing classes without editing their code. To inherit from an existing class, use the Inherits statement, which brings the entire class into your class.

Master It

Explain the inheritance-related attributes of a class's members.

Solution

Any class can be inherited by default. However, you can prevent developers from inheriting your class with the NonIheritable attribute or by creating an abstract class with the MustInherit attribute. Classes marked with this attribute can't be used on their own; they must be inherited by another class. The parent class members can be optionally overridden if they're marked with the Overridable attribute. To prevent derived classes from overriding specific members, use the NotOverridable attribute. Finally, methods that override the equivalent methods of the base class must be prefixed with the Overrides attribute.

Use polymorphism.

Polymorphism is the ability to write members that are common to a number of classes but behave differently, depending on the specific class to which they apply. Polymorphism is a great way of abstracting implementation details and delegating the implementation of methods with very specific functionality to the derived classes.

Master It

The parent class Person represents parties, and it exposes the GetBalance method, which returns the outstanding balance of a person. The Customer and Supplier derived classes implement the GetBalance method differently. How will you use this method to find out the balance of a customer and/or supplier?

Solution

If you have a Customer or Supplier object, you can call the GetBalance method directly. If you have a collection of objects of either type, you must first cast them to their parent type and then call the GetBalance method.

Chapter 11: The Framework at Large

Handle files with the My component.

The simplest method of saving data to a file is to call one of the WriteAllBytes or WriteAllText methods of the My.Computer.FileSystem component. You can also use the IO namespace to set up a Writer object to send data to a file and a Reader object to read data from the file.

Master It

Show the statements that save a TextBox control's contents to a file and the statements that reload the same control from the data file. Use the My.Computer.FileSystem component.

Solution

The following statement saves the control's Text property to a file whose path is stored in the filename variable. Prompt users with the File Open dialog box for the path of the file and then use it in your code:

My.Somputer.FileSystem.WriteAllText(filename, TextBox1.Text, True)

To read the data back and display it on the same control, use the following statement:

TextBox1.Text = My.Computer.FileSystem.ReadAllText(filename)
Write data to a file with the IO namespace.

To send data to a file you must set up a FileStream object, which is a channel between the application and the file. To send data to a file, create a StreamWriter or BinaryWriter object on the appropriate FileStream object. Likewise, to read from a file, create a StreamReader or BinaryReader on the appropriate FileStream object. To send data to a file, use the Write and WriteString methods of the appropriate StreamWriter object. To read data from the file, use the Read, ReadBlock, ReadLine, and ReadToEnd methods of the StreamReader object.

Master It

Write the contents of a TextBox control to a file using the methods of the IO namespace.

Solution

Begin by setting up a FileStream object to connect your application to a data file. Then create a StreamWriter object on top of the FileStream object and use the Write method to send data to the file. Don't forget to close both streams when you're done.

Dim FS As FileStream
FS = New FileStream(filename, FileMode.Create)
Dim SW As New StreamWriter(FS)
SW.Write(TextBox1.Text)
SW.Close
FS.Close

To read the data back and reload the TextBox control, set up an identical FileStream object, then create a StreamReader object on top of it, and finally call its ReadToEnd method:

Dim FS As New FileStream(filename,
              IO.FileMode.OpenOrCreate, IO.FileAccess.Write)
Dim SR As New StreamReader(FS)
TextBox1.Text = SR.ReadToEnd
FS.Close
SR.Close
Manipulate folders and files.

The IO namespace provides the Directory and File classes, which represent the corresponding entities. Both classes expose a large number of methods for manipulating folders (CreateDirectory, Delete, GetFiles, and so on) and files (Create, Delete, Copy, OpenRead, and so on).

Master It

How will you retrieve the attributes of a drive, folder, and file using the IO namespace's classes?

Solution

Start by creating a DriveInfo, DirectoryInfo, and FileInfo object for a specific drive, folder, and file respectively by specifying the name of the appropriate entity as an argument:

Dim DrvInfo As New DriveInfo("C:")
Dim DirInfo As New DirectoryInfo("C:Program Files")
Dim FInfo As New FileInfo("C:Program FilesMy AppsReadme.txt")

Then enter the name of any of these variables and the following period to see the members they expose in the IntelliSense list. The available space on drive C: is given by the property DrvInfo.AvailableFreeSpace. The attributes of the Program Files folder are given by the DirInfo.Attributes property. Finally, the length of the Readme.txt file is given by the property FInfo.Length.

Use the Char data type to handle characters.

The Char data type, which is implemented with the Char class, exposes methods for handling individual characters (IsLetter, IsDigit, IsSymbol, and so on). We use the methods of the Char class to manipulate users' keystrokes as they happen in certain controls (mostly the TextBox control) and to provide immediate feedback.

Master It

You want to develop an interface that contains several TextBox controls that accept numeric data. How will you intercept the user's keystrokes and reject any characters that are not numeric?

Solution

You must program the control's KeyPress event handler, which reports the character that was pressed. The following event handler rejects any non-numeric characters entered in the TextBox1 control:

Private Sub TextBox1_KeyPress(
            ByVal sender As Object,
            ByVal e As System.Windows.Forms.KeyPressEventArgs)
            Handles TextBox1.KeyPress
    Dim c As Char = e.KeyChar
    If Not (Char.IsDigit(c) Or Char.IsControl(c)) Then
        e.Handled = True
    End If
End Sub
Use the StringBuilder class to manipulate large or dynamic strings.

The StringBuilder class is very efficient at manipulating long strings, but it doesn't provide as many methods for handling strings. The StringBuilder class provides a few methods to insert, delete, and replace characters within a string. Unlike the equivalent methods of the String class, these methods act directly on the string stored in the current instance of the StringBuilder class.

Master It

Assuming that you have populated a ListView control with thousands of lines of data from a database, how will you implement a function that copies all the data to the Clipboard?

Solution

To copy the ListView control's data, you must create a long string that contains tab-delimited strings and then copy it to the Clipboard. Each cell's value must be converted to a string and then appended to a StringBuilder variable. Consecutive rows will be separated by a carriage return/line feed character.

Start by declaring a StringBuilder variable:

Dim SB As New System.Text.StringBuilder

Then write a loop that iterates through the items in the ListView control:

Dim LI As ListViewItem
For Each LI In ListView1.Items
' append current row's cell values to SB
    SB.Append(vbCrLf)
Next

In the loop's body, insert another loop to iterate through the subitems of the current item:

Dim LI As ListViewItem
For Each LI In ListView1.Items
    Dim subLI As ListViewItem.ListViewSubItem
    For Each subLI In LI.SubItems
        SB.Append(subLI.Text & vbTab)
    Next
    SB.Remove(SB.Length – 1, 1)  ' remove last tab
    SB.Append(vbCrLf)
Next
Use the DateTime and TimeSpan classes to handle dates and time.

The Date class represents dates and time, and it exposes many useful shared methods (such as the IsLeap method, which returns True if the year passed to the method as an argument is leap; the DaysInMonth method; and so on). It also exposes many instance methods (such as AddYears, AddDays, AddHours, and so on) for adding time intervals to the current instance of the Date class as well as many options for formatting date and time values.

The TimeSpan class represents time intervals — from milliseconds to days — with the FromDays, FromHours, and even FromMilliseconds methods. The difference between two date variables is a TimeSpan value, and you can convert this value to various time units by using methods such as TotalDays, TotalHours, TotalMilliseconds, and so on. You can also add a TimeSpan object to a date variable to obtain another date variable.

Master It

How will you use the TimeSpan class to accurately time an operation?

Solution

To time an operation, you must create a DateTime variable and set it to the current date and time just before the statements you want to execute:

Dim TStart As DateTime = Now

Right after the statements you want to time have been executed, create a new TimeSpan object that represents the time it took to execute the statements. The duration of the TimeSpan object is the difference between the current time and the time stored in the TStart variable:

Dim duration As New TimeSpan
Duration = Now.Subtract(TStart)

The duration variable is a time interval, and you can use the methods of the TimeSpan class to express this interval in various units: duration.MilliSeconds, duration.Seconds, and so on.

Generate graphics by using the drawing methods.

Every object you draw on, such as forms and PictureBox controls, exposes the CreateGraphics method, which returns a Graphics object. The Paint event's e argument also exposes the Graphics object of the control or form. To draw something on a control, retrieve its Graphics object and then call the Graphics object's drawing methods.

Master It

Show how to draw a circle on a form from within the form's Paint event handler.

Solution

The following statements in the form's Paint event handler will draw a circle at the center of Form1:

Private Sub Form1_Paint(
            ByVal sender as Object,
            ByVal e As System.Windows.Forms.PaintEventArgs)
            Handles Me.Paint
Dim diameter = Math.Min(Me.Width, Me.Height)/2
e.Graphics.DrawEllipse(Pens.Blue,
                 New RectangleF((Me.Width – diameter) / 2,
                 (Me.Height – diameter) / 2, diameter, diameter))
End Sub

There's no DrawCircle method; the DrawEllipse method accepts as arguments a Pen object and a rectangle that encloses the circle to be drawn. If the rectangle is a square, then the equivalent ellipse will be a circle. To force the form to be redrawn every time it's resized, you must also insert the following statement in the form's Load event handler:

Me.SetStyle(ControlStyles.ResizeRedraw, True)
Use the printing controls and dialog boxes.

To print with the .NET Framework, you must add an instance of the PrintDocument control to your form and call its Print method. To preview the same document, you simply assign the PrintDocument object to the Document property of the PrintPreviewDialog control and then call the ShowDialog method of the PrintPreviewDialog control to display the preview window. You can also display the Print dialog box, where users can select the printer to which the output will be sent, and the Page Setup dialog box, where users can specify the page's orientation and margins. The two dialog boxes are implemented with the PrintDialog and PageSetupDialog controls.

Master It

Explain the process of generating a simple printout. How will you handle multiple report pages?

Solution

Both the PrintDocument.Print and the PrintPreviewDialog.ShowDialog methods fire the PrintPage event of the PrintDocument control. The code that generates the actual printout must be placed in the PrintPage event handler, and the same code will generate the actual printout on the printer (if you're using the PrintDocument control) or a preview of the printout (if you're using the PrintPreviewDialog control).

It's your responsibility to terminate each page and start a new one every time you complete the current page by setting the HasMorePages property when you exit the PrintPage event handler. If the HasMorePages property is True, the PrintPage event is fired again, until the HasMorePages property becomes False.

Any static variables you use to maintain state between successive invocations of the PrintPage event handler, such as the page number, must be reset every time you start a new printout. A good place to initialize these variables is the BeginPrint event handler.

Master It

Assuming that you have displayed the Page Setup dialog box control to the user, how will you draw a rectangle that delimits the printing area on the page, taking into consideration the user-specified margins?

Solution

First, set up a few variables to store the page's margins, as specified by the user on the Page Setup dialog box:

Dim LeftMargin, RightMargin, TopMargin, BottomMargin as Integer
With PrintDocument1.DefaultPageSettings
    LeftMargin = .Left
    RightMargin = .Right
    TopMargin = .Top
    BottomMargin = .Bottom
End With

Then calculate the dimensions of the rectangle that delimits the printable area on the page:

Dim PrintWidth, PrintHeight As Integer
With PrintDocument1.DefaultPageSettings.PaperSize
    PrintWidth = .Width – LeftMargin – RightMargin
    PrintHeight = .Height – TopMargin – BottomMargin
End With

The rectangle you want to draw should start at the point (LeftMargin, TopMargin) and extend PrintWidth points to the right and PrintHeight points down.

Finally, insert the following statements in the PrintPage event handler to draw the rectangle:

Dim R As New Rectangle(LeftMargin, TopMargin, PrintWidth, PrintHeight)
e.Graphics.DrawRectangle(Pens.Black, R)

Chapter 12: Storing Data in Collections

Make the most of arrays.

The simplest method of storing sets of data is to use arrays. They're very efficient, and they provide methods to perform advanced operations such as sorting and searching their elements. Use the Sort method of the Array class to sort an array's elements. To search for an element in an array, use the IndexOf and LastIndexOf methods, or use the BinarySearch method if the array is sorted. The BinarySearch method always returns an element's index, which is a positive value for exact matches and a negative value for near matches.

Master It

Explain how you can search an array and find exact and near matches.

Solution

The most efficient method of searching arrays is the BinarySearch method, which requires that the array is sorted. The simplest form of the BinarySearch method is the following:

Dim idx As Integer
idx = System.Array.BinarySearch(arrayName, object)

The BinarySearch method returns an integer value, which is the index of the object you're searching for in the array. If the object argument is not found, the method returns a negative value, which is the negative of the index of the next larger item minus one. The following statements return an exact or near match for the word srchWord in the words array:

Dim wordIndex As Integer =
           Array.BinarySearch(words, srchWord)
If wordIndex >= 0 Then  ' exact match!
    MsgBox("An exact match was found for " &
           " at index " & wordIndex.ToString)
Else                    ' Near match
    MsgBox("The nearest match is the word " &
           words(-wordIndex - 1) &
           " at " & (-wordIndex - 1).ToString)
End If
Store data in collections such as List and Dictionary collections.

In addition to arrays, the Framework provides collections, which are dynamic data structures. The most commonly used collections are the List and the Dictionary. Collections are similar to arrays, but they're dynamic structures. List and ArrayList collections store lists of items, whereas Dictionary and HashTable collections store key-value pairs and allow you to access their elements via a key. You can add elements by using the Add method and remove existing elements by using the Remove and RemoveAt methods.

Dictionary collections provide the ContainsKey and ContainsValue methods to find out whether the collection already contains a specific key or value as well as the GetKeys and GetValues methods to retrieve all the keys and values from the collection, respectively. As a reminder, the List and Dictionary collections are strongly typed. Their untyped counterparts are the ArrayList and HashTable collections.

Master It

How will you populate a Dictionary with a few pairs of keys/values and then iterate though the collection's items?

Solution

To populate the Dictionary, call its Add method and pass the item's key and value as arguments:

Dim Dict As New Dictionary(Of Object, Object)
Dict.Add("key1", item1)
Dict.Add("key2", item2)

To iterate through the items of a Dictionary collection, you must first extract all the keys and then use them to access the collection's elements. The following code segment prints the keys and values in the Dict variable, which is an instance of the Dictionary class:

Dim Dict As New Dictionary(Of Object, Object)
Dict.Add("1", "A string value")
Dict.Add(1, "Another string value")
Dict.Add("2", 2)
Dim element, key As Object
For Each key In Dict.keys
    element = Dict.Item(key)
    Debug.WriteLine("Item type = " & element.GetType.ToString
    Debug.WriteLine("Key= " & Key.ToString)
    Denug.WriteLine("Value= " & element.ToString)
Next
Sort and search collections with custom comparers.

Collections provide the Sort method for sorting their items and several methods to locate items: IndexOf, LastIndexOf, and BinarySearch. Both sort and search operations are based on comparisons, and the Framework knows how to compare values' types only (Integers, Strings, and the other primitive data types). If a collection contains objects, you must provide a custom function that knows how to compare two objects of the same type.

Master It

How do you specify a custom comparer function for a collection that contains Rectangle objects?

Solution

First you must decide how to compare two object variables of the same type. For the purposes of this exercise, you can consider two rectangles equal if their perimeters are equal. To implement a custom comparer, write a class that implements the IComparer interface. This class should contain a single method, the Compare method, which compares two objects and returns one of the values −1, 0, and 1:

Class RectangleComparer : Implements IComparer
   Public Function Compare(
       ByVal o1 As Object, ByVal o2 As Object)
       As Integer Implements IComparer.Compare
      Dim R1, R2 As Rectangle
      Try
         R1 = CType(o1, Rectangle)
         R2 = CType(o2, Rectangle)
      Catch compareException As system.Exception
         Throw (compareException)
         Exit Function
      End Try
     Dim perim1 As Integer = 2 * (R1.Width+R1.Height)
     Dim perim2 As Integer = 2 * (R2.Width+R2.Height)
      If perim1 < perim2 Then
         Return −1
      Else
If perim1 > perim2 Then
            Return 1
         Else
            Return 0
         End If
      End If
   End Function
End Class

Once this class is in place, you can pass an instance of it to the Sort method. The following statement sorts the items of the Rects ArrayList collection, assuming that it contains only Rectangles:

Rects.Sort(New RectangleComparer)

If you want to search the collection for a Rectangle object with the BinarySearch method, you must pass as arguments to the method not only the object you're searching for but also an instance of the custom comparer:

Rects.BinarySearch(
        New Rectangle(0, 0, 33, 33), comparer)

Chapter 13: XML in Modern Programming

Create XML documents.

XML documents can be built easily with the XElement and XAttribute classes. XElement represents an element, and its constructor accepts as arguments the element's name and either the element's value or a series of attributes and nested elements. XAttribute represents an attribute, and its constructor accepts as arguments the attribute's name and its value. You can also assign an XML document directly to an XElement.

Master It

Create the XML segment that describes an object of the Item type, defined by the following class:

Class Item
     Property ID As String
     Property Name As String
     Property Prices As Price
     Property Name As String
Class Price
          Property Retail As PriceDetails
          Property WholeSale As PriceDetails
          Class PriceDetails
               Property Price As Decimal
               Property VolumeDiscount As Decimal
End Class
Class Dimension
     Property Width As Decimal
Property Height As Decimal
     Property Depth As Decimal
End Class
Solution

The first technique is called functional construction, and you build the XML document by appending XElements and XAttributes to a variable:

Dim prod = New XElement("Item", New XAttribute("ID", "A001"),
           New XElement("Name", "ProductName"),
           New XElement("Price",
               New XElement("Retail",
                            New XAttribute("Price", "10.95"),
                            New XAttribute("VolumeDiscount", "0.25")),
               New XElement("WholeSale",
                            New XAttribute("Price", "8.50"),
                            New XAttribute("VolumeDiscount", "0.20"))))

Alternatively, you can declare a variable and set it to the equivalent XML document (which is the same document that the expression prod.ToString will return):

Dim prod = <Item ID="A001">
                <Name>ProductName</Name>
                <Price>
                    <Retail Price="10.95" VolumeDiscount="0.25"/>
                    <WholeSale Price="8.50" VolumeDiscount="0.20"/>
                </Price>
           </Item>
Navigate through an XML document and locate the information you need.

The XElement class provides a number of methods for accessing the contents of an XML document. The Elements method returns the child elements of the current element by the name specified with the argument you pass to the method as a string. The Element method is quite similar, but it returns the first child element by the specified name. The Descendants method returns all the elements by the specified name under the current element, regardless of whether they're direct children of the current element. Finally, the Attribute method returns the value of the attribute by the specified name of the current element.

Master It

Assuming an XML document with the following structure, write the expressions to retrieve all cities in the document and all cities under the third country in the document.

<Countries>
   <Country>
      <City> ... </City>
      <City> ... </City>
   </Country>
   <Country>
   ...
   </Country>
   ...
</Countries>
Solution

The following expression returns all cities in the document:

Dim cities =
countries.Elements("Country").Elements("Cities").Elements("City")

The cities variable is an IEnumerable collection of XElement objects. Likewise, to retrieve the cities of the third country, you must retrieve the Elements collection of the third element:

Dim countryCities =
countries.Elements("Country")(2).Elements("Cities").Elements("City")
Master It

Assuming that both country and city names are specified in the document with the Name element, explain the difference between the queries:

Dim q1 = countries.Elements("Country").Elements("Name")
Dim q2 = countries.Descendants("Name")
Solution

The first query returns all country names in the document, because the Elements method retrieves all elements that are directly under the element to which it's applied (not their children's children, even if the same element name is repeated). The second query returns all country and city names, because the Descendants method retrieves all elements by the specified name under the element to which it's applied (regardless of their nesting).

Convert arbitrary objects into XML documents and back with serialization.

Serialization is the process of converting an object into a stream of bytes. This process (affectionately known as dehydration) generates a stream of bytes or characters, which can be stored or transported. To serialize an object, you can use the BinaryFormatter or SoapFormatter class. You can also use the XmlSerializer class to convert objects into XML documents. All three classes expose a Serialize class that accepts as arguments the object to be serialized and a stream object and writes the serialized version of the object to the specified stream. The opposite of serialization is called deserialization. To reconstruct the original object, you use the Deserialize method of the same class you used to serialize the object.

Master It

Describe the process of serializing an object with the XmlSerializer class.

Solution

First create a Stream object to accept the result of serialization; this stream is usually associated with a file:

Dim saveFile As New FileStream("Objects.xml", FileMode.Create)

Then create an instance of the XmlSerializer class, passing to its construction the type of object you want to serialize:

Dim serializer As New XmlSerializer(custom_type)

And finally call the serializer object's Serialize method, passing as an argument the object you want to serialize:

serializer.Serialize(stream, object)

Chapter 14: An Introduction to LINQ

Perform simple LINQ queries.

A LINQ query starts with the structure From variable Incollection, where variable is a variable name and collection is any collection that implements the IEnumerable interface (such as an array, a typed collection, or any method that returns a collection of items). The second mandatory part of the query is the Select part, which determines the properties of the variable you want in the output. Quite often you select the same variable that you specify in the From keyword. In most cases, you apply a filtering expression with the Where keyword. Here's a typical LINQ query that selects filenames from a specific folder:

Dim files =
        From file In
          IO.Directory.GetFiles("C:Documents")
          Where file.EndsWith("doc")
        Select file
Master It

Write a LINQ query that calculates the sum of the squares of the values in an array.

Solution

To calculate a custom aggregate in a LINQ query, you must create a lambda expression that performs the aggregation and passes it as an argument to the Aggregate method. The lambda expression accepts two arguments, the current value of the aggregate and the current value, and returns the new aggregate. Such a function would have the following signature and implementation:

Function(aggregate, value)
    Return(aggregate + value ˆ2)
End Function

To specify this function as a lambda expression in a LINQ query, call the collection's Aggregate method as follows:

Dim sumSquares = data.Aggregate(
    Function(sumSquare As Long, n As Integer)
             sumSquare + n ˆ 2)
Create and process XML files with LINQ to XML.

LINQ to XML allows you to create XML documents with the XElement and XAttribute classes. You simply create a new XElement object for each element in your document and create a new XAttribute object for each attribute in the current element. Alternatively, you can simply insert XML code in your VB code. To create an XML document dynamically, you can insert embedded expressions that will be evaluated by the compiler and replaced with their results.

Master It

How would you create an HTML document with the filenames in a specific folder?

Solution

To generate a directory listing, you must first implement the LINQ query that retrieves the desired information. The query selects the files returned by the GetFiles method of the IO.Directory class:

Dim files = From file In
                IO.Directory.GetFiles(path)
            Select New IO.FileInfo(file).Name,
            New IO.FileInfo(file).Length

Now you must embed this query into an XML document using expression holes. The XML document is actually an HTML page that displays a table with two columns, the file's name and size, as shown next:

Dim smallFilesHTML = <html>
      <table><tr>
         <td>FileName</td>
         <td>FileSize</td></tr>
         <%= From file In
             IO.Directory.GetFiles("C:")
             Select <tr><td><%= file %></td> ,
             <td>
             <%= New IO.FileInfo(file).Length %>
             </td></tr>
          %>
       </table></html>
Process relational data with LINQ to SQL.

LINQ to SQL allows you to query relational data from a database. To access the database, you must first create a DataContext object. Then you can call this object's GetTable method to retrieve a table's rows or the ExecuteQuery method to retrieve selected rows from one or more tables with a SQL query. The result is stored in a class designed specifically for the data you're retrieving via the DataContext object.

Master It

Explain the attributes you must use in designing a class for storing a table.

Solution

The class must be decorated with the <Table> attribute that specifies the name of the table that will populate the class:

<Table(Name:="Customers")>Public Class Customers
...
End Class

Each property of this table must be decorated with the <Column> attribute that specifies the name of the column from which the property will get its value:

<Column(Name:= "CompanyName")>
     Public Property Company
...
End Property

When you call the GetTable method of the DataContext class, pass the name of the class as an argument, and the DataContext class will create a new instance of the class and populate it.

Chapter 15: Programming with ADO.NET

Store data in relational databases.

Relational databases store their data in tables and are based on relationships between these tables. The data are stored in tables, and tables contain related data, or entities, such as persons, products, orders, and so on. Relationships are implemented by inserting columns with matching values in the two related tables.

Master It

How will you relate two tables with a many-to-many relationship?

Solution

A many-to-many relationship can't be implemented with a primary/foreign key relationship between two tables. To create a many-to-many relationship, you must create a new table that relates the other two tables to one another by implementing two one-to-many relationships. Consider the Titles and Authors tables, which have a many-to-many relationship, because a title can have many authors and the same author may have written multiple titles. To implement this relationship, you must create an intermediate table, the TitleAuthors table, which is related to both the Titles and Authors table with a one-to-many relationship. The TitleAuthors table should store title and author IDs. The TitleAuthor.TitleID column is the foreign key to the relationship between the Titles and TitleAuthors tables. Likewise, the TitleAuthor.AuthorID column is the foreign key to the relationship between the TitleAuthor and Authors tables.

Query databases with SQL.

Structured Query Language (SQL) is a universal language for manipulating tables. SQL is a nonprocedural language, which specifies the operation you want to perform against a database at a high level, unlike a traditional language such as Visual Basic, which specifies how to perform the operation. The details of the implementation are left to the DBMS. SQL consists of a small number of keywords and is optimized for selecting, inserting, updating, and deleting data.

Master It

How would you write a SELECT statement to retrieve selected data from multiple tables?

Solution

The SELECT statement's FROM clause should include the names of two or more tables, which must be somehow related. To relate the tables, use the JOIN clause, and specify the primary/foreign keys of the join:

SELECT column1, column2, ...
FROM table1 T1 INNER JOIN table2
     ON T1.primaryKey = T2.foreignKey
INNER JOIN table3 T3
     ON T2.primaryKey = T3.foreignKey
WHERE criteria

Pay attention to the type of join you specify. An inner join requires that the two columns match and excludes null values. A left join takes into consideration all the qualifying rows of the left table, including the ones that have null in their foreign key column. A right join takes into consideration all the qualifying rows of the right table, including the ones that have null in their foreign key column. A full outer join is a combination of the right and left joins — it takes into consideration null values from both tables involved in the query.

Submit queries to the database using ADO.NET.

ADO.NET is the component of the Framework that provides the mechanism to contact a database, submit queries, and retrieve the results of a query. There are two types of queries you can execute against a database: selection queries that retrieve data from the database based on certain criteria you supply and action queries that manipulate the data at the database. Action queries do not return any results, except for the number of rows that were affected by the query.

Master It

Describe the basic mechanism for submitting a selection query to the database and reading the results returned by the query.

Solution

First you must connect to the database with a SqlConnection object. The SqlConnection class's constructor accepts as argument the credentials it must use to connect to the database. Then you must create a SqlCommand object, which exposes the CommandText property. Assign the query you want to execute against the database, and optionally set the CommandType property. You must also set the Connection object to the SqlConnection object, open the connection to the database, and finally call the SqlCommand object's ExecuteQuery method for selection queries or call the ExecuteNonQuery method for action queries.

The ExecuteNonQuery method returns an integer, which is the number of rows affected by the query. The ExecuteQuery method returns a DataReader object, which you can use to iterate through the results of the query. Call the Read method to read the next row, and access each row's column's with the Item property of the DataReader class. Here is the pseudocode for accessing the rows of a query that retrieves customer information from the Northwind database:

CMD.CommandText = "SELECT * FROM Customers WHERE Country = 'Germany'"
CN.Open()
Dim RDR As SqlDataReader
RDR = CMD.ExecuteReader
While RDR.Read
    ' Call the RDR.Item(col_name) method
    ' to read a specific column of the current row
    ' RDR.Item("CustomerID"), RDR.Item("Country") and so on
    ' Use the RDR.IsDBNull method to determine whether
    ' a column is Null, because Null values must be
    ' handled specially
End While
CN.Close()

It's imperative that you read the data off the DataReader as soon as possible and then close the connection to the database as soon as you are done.

Chapter 16: Developing Data-Driven Applications

Create and populate DataSets.

DataSets are data containers that reside at the client and are populated with database data. The DataSet is made up of DataTables, which correspond to database tables, and you can establish relationships between DataTables, just like relating tables in the database. DataTables, in turn, consist of DataRow objects.

Master It

How do you populate DataSets and then submit the changes made at the client to the database?

Solution

To populate a DataSet, you must create a DataAdapter object for each DataTable in the DataSet. The DataAdapter class provides the SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand properties, which are initialized to the SQL statements that retrieve, set, update, and delete rows from the corresponding database tables. You can use the CommandBuilder object to build the INSERT, UPDATE, and DELETE statements from the SELECT statement, which you must supply. After these properties have been set, you can populate the corresponding DataTable by calling the Fill method of its DataAdapter object. If the DataSet contains relationships, you must fill the parent tables before the child tables.

Establish relations between tables in the DataSet.

You can think of the DataSet as a small database that resides at the client, because it consists of tables and the relationships between them. The relations in a DataSet are DataRelation objects, which are stored in the Relations property of the DataSet. Each relation is identified by a name, the two tables it relates, and the fields of the tables on which the relation is based.

Master It

How do you navigate through the related rows of two tables?

Solution

To navigate through the rows of two related tables, the DataRow object that represents a row in a DataTable provides the GetChildRows method, which returns the current row's child rows as an array of DataRow objects, and the GetParentRow/GetParentRows methods, which return the current row's parent row(s). GetParentRow returns a single DataRow, and GetParentRows returns an array of DataRow objects. Because a DataTable may be related to multiple DataTables, you must also specify the name of the relation as an argument to these methods. The following statements retrieve the child rows of a specific category row in the DataTable with the rows of the Categories table and a specific supplier, respectively.

DS.Categories(iRow).GetChildRows("CategoriesProducts")
DS.Suppliers(iRow).GetChildRows("SupplierProducts")
Submit changes in the DataSet to the database.

The DataSet maintains not only data at the client but their states and versions too. It knows which rows were added, deleted, or modified (the DataRowState property), and it also knows the version of each row read from the database and the current version (the DataRowVersion property).

Master It

How will you submit the changes made to a disconnected DataSet to the database?

Solution

To submit the changes made to an untyped DataSet, you must call the Update method of each DataAdapter object. You must call the Update method of the DataAdapter objects that correspond to the parent tables first and then the Update method of the DataAdapter objects that correspond to the child tables. You can also submit individual rows to the database, as well as arrays of DataRow objects through the overloaded forms of the Update method.

Chapter 17: Using the Entity Data Model

Employ deferred loading when querying the Entity Data Model.

The Entity Framework supports the deferred loading (lazy loading) of entities. When deferred loading is activated, entities in navigation properties are loaded on demand, only after they are accessed. In cases when you are not certain that the related entity will be accessed (for example, when loading is dependent on a user action), you can initially load only the root entity and load the related entities only when they are requested.

Master It

How do you activate deferred loading in the Entity Framework?

Solution

To enable deferred loading when querying the Entity Framework, set the DeferredLoadingEnabled property of the ContextOptions property of ObjectContext to True. For example, use context.ContextOptions.DeferredLoadingEnabled = True.

Use entity inheritance features in the Entity Framework.

In the EDM, an inheritance relationship can be established between entities. When two entities participate in an inheritance relationship, the child entity inherits all the properties of the parent entity. When working with such an entity in .NET code, you can get major benefits from code reuse based on inheritance.

Master It

Explain how the Entity Framework can map an inheritance relationship between entities to tables in the database. Why is maintaining the inheritance relationship between the entities not easily accomplished with relational databases?

Solution

The Entity Framework employs two basic mapping strategies for mapping the inheritance relationship on the database level. In the table-per-type strategy, each type is mapped to a separate table. The child table contains only child-specific columns. Both the parent and child table are obliged to have identical primary keys. To retrieve a child type, a join between the parent and child tables has to be performed.

In the table-per-hierarchy mapping strategy, all types are mapped to the same table. A special discriminator column is used to identify the specific type that each row represents.

Since relational databases do not natively support an inheritance relationship, significant amounts of application code need to be written to implement this relationship on the database level. The Entity Framework provides this feature out of the box and thus can save developers from writing significant amounts of boilerplate code.

Create and query related entities.

In the Entity Data Model, you can establish one-to-many or many-to-many associations between entities. The association can be established by connecting related entities with the Association tool in the EDM diagram. When querying such entities, a related entity or set of entities can be accessed through generated navigation properties.

Master It

In the Books and Authors application (used as a sample application in Chapter 17), add a SalesByMonth form that will display the number of copies sold in a month for each title in the database. Modify the Books and Authors EDM so that the model can accommodate monthly sales information for each title.

Solution

Add the SaleByMonth entity to the Books and Authors EDM, and use it to store the monthly sales information. Establish a one-to-many relationship between the Book and SaleByMonth entities. Write the query to retrieve the necessary information and display it on the form.

Start by modifying the EDM:

  1. Add a new entity to the EDM, and name it SaleByMonth.

  2. Rename the entity set of SaleByMonth to SalesByMonth.

  3. Add a Month scalar property of type Int16 to the SaleByMonth entity.

  4. Add a Year scalar property of type Int16 to the SaleByMonth entity.

  5. Add a CopiesSold scalar property of type Int64 to the SaleByMonth entity.

  6. Establish a one-to-many association between the Book and SaleByMonth entities.

  7. Add a form named SaleByMonthForm to the project. Add one DataGridView control and one button control named Display to the SaleByMonthForm form.

  8. Fill the DataGridView from the query in the Display button's Click event handler.

Listing A.1 shows the code for the Display button event handler.

Example A.1. Using TransactionScope for enlisting external operations

Private Sub Display_Click(ByVal sender As System.Object,
                          ByVal e As System.EventArgs) Handles
                          Display.Click
    Dim context As New BooksAndAuthorsContainer
    Dim books = context.Books.Include("Sales")
    For Each book As Book In books
        For Each saleByMonth In book.Sales
            gridResult.Rows.Add(New String() {
                book.ISBN, book.Title,
                saleByMonth.Month.ToString & saleByMonth.Year.ToString(),
                saleByMonth.CopiesSold.ToString()})
        Next
    Next
End Sub

Chapter 18: Building Data-Bound Applications

Design and use typed DataSets.

Typed DataSets are created with visual tools at design time and allow you to write type-safe code. A typed DataSet is a class created by the wizard on the fly, and it becomes part of the project. The advantage of typed DataSets is that they expose functionality specific to the selected tables and can be easily bound to Windows forms. The code that implements a typed DataSet adds methods and properties to a generic DataSet, so all the functionality of the DataSet object is included in the autogenerated class.

Master It

Describe the basic components generated by the wizard when you create a typed DataSet with the visual tools of Visual Studio.

Solution

The basic components of the class that implements a typed DataSet are as follows: the DataSet, which describes the entire DataSet; the BindingNavigator, which links the data-bound controls on the form to the DataSet; and the TableAdapter, which links the DataSet to the database. The DataSet component is based on the DataSet class and enhances the functionality of an untyped DataSet by adding members that are specific to the data contained in the DataSet. If the DataSet contains the Products table, the typed DataSet exposes the ProductsRow class, which represents a row of the Products table. The ProductsRow class, in turn, exposes the columns of the table as properties.

The BindingSource class allows you to retrieve the current row with its Current property, move to a specific row by setting the Position property, and even suspend temporarily and restore data binding with SuspendBinding and ResumeBinding.

The TableAdapter class, which is based on the DataAdapter class, provides methods for loading a DataTable (the Fill method) and submitting the changes made to the DataSet to the database (the Update method). The TableAdapterManager class, which encapsulates the functionality of all TableAdapters on the form, provides the UpdateAll method, which submits the changes in all DataTables to the database.

Bind Windows forms to typed DataSets.

The simplest method of designing a data-bound form is to drop a DataTable, or individual columns, on the form. DataTables are bound to DataGridView controls, which display the entire DataTable. Individual columns are bound to simple controls such as TextBox, CheckBox, and DateTimePicker controls, depending on the column's type. In addition to the data-bound controls, the editor generates a toolbar control with some basic navigational tools and the Add/Delete/Save buttons.

Master It

Outline the process of binding DataTables to a DataGridView control.

Solution

To bind a DataTable to a DataGridView control, locate the desired table in the Data Sources window, set its binding option to DataGridView, and drop the DataTable on the form. The editor will create a DataGridView control on the form and map the control's columns according to the columns of the DataTable. It will also add a toolbar with the basic navigational and editing controls on the form.

To bind two related DataTables on the same form, drop the parent DataTable on the form, and then select the child DataTable under this parent and drop it on the form. To modify the appearance of the DataGridView controls, open their Tasks menu, and choose Edit Columns to see the Edit Columns dialog box, where you can set the appearance of the control's columns.

Compare a LINQ query used to filter data with an eSQL dynamic query.

You can use the AsDataView extension method of the DataTable class to enable binding of the LINQ query results when querying the DataSet in LINQ to DataSet technology. In this chapter, you have seen how a LINQ query can be used to provide filtering capabilities on a data-entry form.

Entity SQL (eSQL) is a query language with syntax similar to Transact-SQL. Entity SQL queries can be embedded inside the Visual Basic code and can be used to query the Entity Data Model provided by the Entity Framework. You saw how to use Entity SQL to construct dynamic queries in Chapter 17.

Master It

Compare LINQ queries to queries written in Entity SQL. Explain the main benefits and drawbacks of each technology.

Solution

LINQ to DataSet technology provides a rich set of querying features for querying the data in the DataSet. LINQ syntax is an integral part of Visual Basic syntax and as such is processed and verified during the compilation process and supported by IntelliSense.

Entity SQL is used inside the Visual Basic code as an embedded query language. Since Entity SQL code is essentially written in the form of string literals inside Visual Basic code, it is not compiled. Such code can count only on reduced IntelliSense support. This and having to learn new language syntax (although fairly similar to Transact-SQL and therefore probably familiar to Visual Basic .NET programmers) are the main drawbacks of Entity SQL compared to LINQ.

Since Entity SQL code is not compiled, Entity SQL code can be constructed at runtime. This is especially handy for writing queries with a large number of criteria combinations that can only be known at runtime. When writing similar queries in LINQ, you have to include all the criteria in the query and then provide the means to activate or deactivate certain criteria. Alternatively, you can write chained LINQ queries. LINQ code can be more complex to write and less efficient to execute than Entity SQL code.

Chapter 19: Accessing the Web

Access a website on the Internet using the WebClient class.

The WebClient class provides an easy and simple way to access resources on the Web programmatically from Visual Basic code. The WebClient class implements many features of HTTP, making it easy to access the sites on the Web in the same way the browser application does. The web server will not distinguish a request coming from a WebClient site from one coming from a user-operated web browser.

The WebClient class can be very useful in HTML screen scraping scenarios, where the data to be extracted from HTML is meant to be read by a human, or in lightweight web service protocols like REST and/or AJAX-styled XML and JSON over HTTP.

Master It

Use the Headers property of the WebClient class to fine-tune HTTP requests. Trick Google into believing that a request that you are sending from your Visual Basic application is coming from some mobile device.

Solution

The WebClient class permits adding different headers to your HTML requests through its Headers property. The header used to identify the type of client sending the request is the "user-agent" header. You need to add this header to your HTTP request. The value of the header should be the string sent by some mobile device. Browsing the Internet, I found that some LG mobile phones send the following string value as their "user-agent": "L1G-CU920/V1.0p Obigo/Q05A Profile/MIDP-2.0 Configuration/CLDC-1.1".

If you create a new Windows Forms application and add a Download button to the form, here is the code you need to add to Download button's event handler in order to receive Google's default search page formatted for mobile devices:

Dim client As New WebClient
client.Headers.Add("user-agent",
"L1G-CU920/V1.0p Obigo/Q05A Profile/MIDP-2.0 Configuration/CLDC-1.1")
Dim response = client.DownloadString("http://www.google.com")
Console.WriteLine(response)

This code will write the response to the Output window. Now, if you copy this output, save it to a googlemobile.html file, and open the file with your web browser, you will see the Google search page as shown in Figure A.1.

Google search page formatted for a mobile device

Figure A.1. Google search page formatted for a mobile device

Use a WebBrowser control to add web browser functionality to your Windows Forms application.

The WebBrowser control provides all the basic functionality of a browser in a form of Windows Forms control. Visually, it consists only of a main browser window. To provide additional functionality, like an address bar and Back, Forward, Refresh, and other buttons, you will have to add the appropriate controls and program them yourself. The WebBrowser control uses the same browser engine as Internet Explorer.

A WebBrowser control's behavior can be customized to a large degree. You can decide to show or not show the scroll bars, allow or disallow navigation, show or not show the context menu, and so forth. Finally, since the control does not contain the address bar, you can also control which sites a user can access.

Master It

Create a custom web browser that can navigate to a limited number of URLs.

Solution

Use the WebBrowser control to create a browser that can navigate to a limited number of URLs. Start by creating a new Windows Forms project:

  1. Create a new Windows Forms project and name it LimitedBrowser.

  2. Add a ComboBox named cboUrls to the form and set its Dock property to Top.

  3. Add a WebBrowser control to the form.

  4. Fill the Items property of the cboUrls control with the following items:

    http://www.google.com
    http://www.msdn.com
    http://www.yahoo.com
    http://www.sybex.com
  5. Set the Text property of cboUrls to http://www.sybex.com.

If you run the project now, you will see a form with a combo box at the top and a WebBrowser control covering the rest of the form, like the one shown in Figure A.2.

Limited web browser form

Figure A.2. Limited web browser form

All that is left to be done is to make the WebBrowser control navigate as the user selects a different item in the combo box cboUrls. To implement navigation functionality, add the following code to cboUrls's SelectedIndexChanged event hander:

Private Sub cboUrls_SelectedIndexChanged(ByVal sender As System.Object,
    ByVal e As System.EventArgs) Handles cboUrls.SelectedIndexChanged

        WebBrowser1.Navigate(cboUrls.Text)
End Sub

Chapter 20: Building Web Applications

Create a basic XHTML/HTML page.

Building a basic HTML page is a straightforward process using a simple text editor such as Notepad. Knowledge of XHTML/HTML is still a major asset when developing web applications with Visual Studio 2010.

Master It

Develop a web page using HTML that features a heading, some text, an image, and a link to another page. Convert the page to XHTML and verify it by using the W3C verification tool at http://validator.w3.org. You might find that you will need to run the validation a couple of times to get everything right. If you attach and use the style sheet in the following Master It challenge, you will find that validation will be less problematic.

Solution

Note that this solution includes the style sheet created in the next Master It challenge. As in the examples with other listings in this book, some long lines are wrapped here in print, but you can leave them all on one line in your code.

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
 strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
   <head>
      <link rel="stylesheet" type="text/css" href="stylesheet.css" />
      <title>Basic Page</title>
   </head>
   <body>
      <div class="title">
         <h1>Heading</h1>
      </div>
      <div class="content">
         <p>Text</p>
         <img src="myimage.png" height="100" _
 width="100" alt="myimage" />
         <br/>
      </div>
      <div class="menu">
         <a href="http://www.microsoft.com">Microsoft</a>
      </div>
   </body>
</html>
Format a page with CSS.

Cascading Style Sheets (CSS) is a powerful tool for controlling the styles and format of a website. You can manually create style sheets by using a text editor. An understanding of their operation and syntax is a useful skill when manipulating CSS in Visual Studio 2010.

Master It

Create a CSS style sheet that defines the layout of the web page that you developed in the previous task, including a header section, a left-hand navigation section, and a main content section. Include a rollover for the link and apply formatting to the tags that you have used for your heading and text tags. Attach the style sheet to your web page.

Solution

The following code represents the CSS style sheet:

title{
 height:80px;
 background:lightblue;
 margin:5px 10px 10px 10px;
 text-align: center;
 }

menu{
 position: absolute;
 top: 110px;
 left: 20px;
 width: 130px;
 background: silver;
 padding: 10px;
 bottom: 20px;
 }

content{
 background: lightblue;
 padding: 30px;
 position: absolute;
 top: 110px;
 bottom: 20px;
 left: 180px;
 right: 20px
 }

a {
 text-decoration:none;
 color:blue;
 }

a:visited {
 text-decoration:none;
 color:blue;
 }
a:hover {
 text-decoration:none;
 font-weight: bold;
 color:darkblue;
 }

a:active {
 text-decoration:none;
 color:blue;
 }
Set up a master page for your website.

Using master pages is a reliable method of controlling the overall layout and look and feel of your websites and applications. Master pages enable you to achieve a high level of consistency in your design and are particularly useful if the site has multiple developers working on it.

Master It

Create a website with a master page and attached content page. Use appropriate controls to give the master page a page heading, My Page, which will appear on all attached content pages. Use a combination of Button and Label controls on the content page to create a simple Hello World application.

Solution

Start a new website and delete the default.aspx page. Create a new master page and add a Label control to it above the default ContentPlaceHolder control. Format the Label control appropriately as a heading and add a page heading: My Page.

Add a content page to your project. Name the page default.aspx. In the content page, add a Button control and a Label control to the ContentPlaceHolder. (You may need to right-click the ContentPlaceHolder control and choose the Create Custom Content option.) Double-click the button and write the following code to set the text property of the label control to Hello World:

Protected Sub Button1_Click(ByVal sender As Object,
 ByVal e As System.EventArgs) Handles Button1.Click
        Label1.Text = "Hello World"
End Sub
Use some of the ASP.NET intrinsic objects.

ASP.NET objects such as the Response, Request, Session, and Server objects offer a range of important utilities in developing, running, and maintaining your websites and applications. In addition, they give you access to vital information about the client, the server, and any current sessions at runtime.

Master It

Create a simple website with a master page and two attached content pages. Use the Server.Execute method attached to a LinkButton control to navigate between the two content pages.

Solution

Create a new website and delete the default.aspx page. Create a new master page and attach two content pages. Name one of the pages default.aspx and right-click it in Solution Explorer to set the page as the startup page from the drop-down context menu. Name the second page Page2.aspx. Place some distinguishing features on the two pages, such as Label controls with appropriate text content.

Add a LinkButton control to the ContentPlaceHolder in default.aspx. Double-click the LinkButton control and use Server.Execute in the sub for the Click method to create a link to page 2.

Protected Sub LinkButton1_Click(ByVal sender As Object,
   ByVal e As System.EventArgs) Handles LinkButton1.Click
        Server.Execute("Page2.aspx")
End Sub

Chapter 21: Building and Using Web Services

Create a simple ASP.NET web service.

Creating ASP.NET web services is straightforward with Visual Studio. ASP.NET web services provide a great method for delivering data and functionality within a distributed environment, including the Internet.

Master It

Develop an ASP.NET web service that enables the user to add two numbers.

Solution

  1. Open Visual Studio 2010 and choose File

    Chapter 21: Building and Using Web Services
  2. On the New Web Site dialog box, select ASP.NET Web Service and click OK.

  3. In the App_Code/Service.vb file, change the default reference http://tempuri.org to something more relevant to your service.

  4. Replace the default web method, HelloWorld(), with a method of your own. A web method is implemented like a function in VB, and it's decorated with the <WebMethod> attribute.

Consume an ASP.NET web service.

Adding a web reference or service reference to a web service is a key element to creating an application that can consume the web service.

Master It

Create a new website and add a service reference to a web service on your machine.

Solution

  1. Open an existing web service with Visual Studio 2010. Run the application to open an instance of the ASP.NET Development Server that will host the service.

  2. Open a new instance of Visual Studio 2010 and create a new website project.

  3. Right-click the name of the new project in the Solution Explorer and select Add Service Reference from the context menu.

  4. In the Add Service Reference dialog box, type the URL of the web service running in the first instance of Visual Studio (the web service being hosted by the ASP.NET Development Server).

  5. After the service has been discovered, click the OK button to close the dialog box. Now you can create a variable of the same type in your code and access the service's members through this variable.

Create a WCF service.

WCF services are similar to web services, but they give developers more options for deployment and they support more data exchange protocols.

Master It

Outline the steps involved in building a WCF service.

Solution

A WCF service must contain a data contract that specifies the service's data types and is implemented as a class with public properties; an operation contract that specifies the methods of the service and is implemented as an interface; and the actual service that's implemented as a class that contains the code of the various methods. The class that implements the data contract must be marked with the DataContract attribute and the class that implements the interface must be marked with the ServiceContract attribute. Finally, the class that implements the methods must be marked with the ServiceBehavior attribute.

Work with ADO.NET Data Services.

ADO.NET Data Services is a project component that exposes, or surfaces, data as a service through HTTP. Data services are built automatically by Visual Studio based on any data source, and you can access them through URI requests.

Master It

How do you access the methods of an ADO.NET data service?

Solution

You can access the methods of an ADO.NET data service through your browser using URL syntax to pass parameters to the method. To access a table, append the name of the table after the service's name. To access a specific row in the table, specify the desired row's primary key in a pair of parentheses following the table name. To filter a table's rows, use the $filter keyword, passing the filtering expression as parameter value.

You can also create a proxy class that encapsulates the functionality of the data service with the DataSvcUtil.exe utility. Once you have created the proxy, you can create a variable of this type in your code and use it to access the methods of the data service and use LINQ statements to query your data.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.239.166