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.
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.
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.
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.
Describe the process of building a simple Windows application.
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.
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.
How would you declare and initialize a few variables?
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
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"
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.
How will the compiler treat the following statement?
Dim amount = 32
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
).
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.
Create a structure for storing products and populate it with data.
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
Arrays are structures for storing sets of data as opposed to single-valued variables.
How would you declare an array for storing 12 names and another one for storing 100 names and Social Security numbers?
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
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.
Explain briefly the decision statements of Visual Basic.
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.
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.
How will you create multiple overloaded forms of the same function?
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.
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.
Explain the difference between passing arguments by value and passing arguments by reference.
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.
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.
Describe the process of aligning controls on a form.
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
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).
How will you handle certain keystrokes regardless of the control that receives them?
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
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.
How will you execute one or more statements in the context of a structured exception handler?
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.
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.
What are the most important properties of the TextBox control? Which ones would you set in the Properties windows at design time?
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.
How would you implement a control that suggests lists of words matching the characters entered by the user?
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.
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.
How would you locate an item in a ListBox control?
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.
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.
Which event of the ScrollBar control would you code to provide visual feedback to the user?
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
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.
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?
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.
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).
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?
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.
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.
How will you add a TextBox control to your form at runtime and assign a handler to the control's TextChanged
event?
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)
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.
What are the two basic events fired by the ToolStripMenuItem object?
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.
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.
Your application needs to open an existing file. How will you prompt users for the file's name?
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.
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?
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.
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.
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?
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
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.
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
Description for item 1
Description for item 2
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)
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).
How will you set up a TreeView control with a book's contents at design time?
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.
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.
How will you set up a ListView control with three columns to display names, email addresses, and phone numbers at design time?
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.
How would you populate the same control with the same data at runtime?
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)
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.
How do you implement properties and methods in a custom class?
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.
How would you use a constructor to allow developers to create an instance of your class and populate it with initial data?
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.
Which are the default methods of a custom class that you will most likely override with more meaningful definitions?
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.
How should you handle exceptions in a class?
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 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.
When should you overload operators in a custom class, and why?
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.
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.
Describe the process of designing an inherited custom control.
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.
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.
How will you map certain members of a constituent control to custom members of the compound control?
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
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.
Describe the process of developing a user-drawn custom control.
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).
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.
Outline the process of creating a ListBox control that wraps the contents of lengthy items.
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:
Set the control's DrawMode
property to OwnerDrawVariable
.
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.
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.
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.
Explain the inheritance-related attributes of a class's members.
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.
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.
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?
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.
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.
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.
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)
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.
Write the contents of a TextBox control to a file using the methods of the IO
namespace.
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
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).
How will you retrieve the attributes of a drive, folder, and file using the IO
namespace's classes?
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
.
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.
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?
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
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.
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?
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
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.
How will you use the TimeSpan class to accurately time an operation?
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.
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.
Show how to draw a circle on a form from within the form's Paint
event handler.
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)
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.
Explain the process of generating a simple printout. How will you handle multiple report pages?
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.
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?
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)
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.
Explain how you can search an array and find exact and near matches.
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
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.
How will you populate a Dictionary with a few pairs of keys/values and then iterate though the collection's items?
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
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.
How do you specify a custom comparer function for a collection that contains Rectangle objects?
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)
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.
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
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>
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.
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>
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")
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")
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).
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.
Describe the process of serializing an object with the XmlSerializer class.
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)
A LINQ query starts with the structure From
variable In
collection
, 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
Write a LINQ query that calculates the sum of the squares of the values in an array.
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)
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.
How would you create an HTML document with the filenames in a specific folder?
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>
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.
Explain the attributes you must use in designing a class for storing a table.
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.
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.
How will you relate two tables with a many-to-many relationship?
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.
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.
How would you write a SELECT
statement to retrieve selected data from multiple tables?
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.
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.
Describe the basic mechanism for submitting a selection query to the database and reading the results returned by the query.
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.
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.
How do you populate DataSets and then submit the changes made at the client to the database?
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.
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.
How do you navigate through the related rows of two tables?
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")
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).
How will you submit the changes made to a disconnected DataSet to the database?
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.
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.
How do you activate deferred loading in the Entity Framework?
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
.
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.
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?
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.
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.
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.
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:
Add a new entity to the EDM, and name it SaleByMonth
.
Rename the entity set of SaleByMonth
to SalesByMonth
.
Add a Month
scalar property of type Int16 to the SaleByMonth
entity.
Add a Year
scalar property of type Int16 to the SaleByMonth
entity.
Add a CopiesSold
scalar property of type Int64 to the SaleByMonth
entity.
Establish a one-to-many association between the Book
and SaleByMonth
entities.
Add a form named SaleByMonthForm
to the project. Add one DataGridView control and one button control named Display to the SaleByMonthForm
form.
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
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.
Describe the basic components generated by the wizard when you create a typed DataSet with the visual tools of Visual Studio.
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.
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.
Outline the process of binding DataTables to a DataGridView control.
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.
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.
Compare LINQ queries to queries written in Entity SQL. Explain the main benefits and drawbacks of each technology.
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.
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.
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.
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.
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.
Create a custom web browser that can navigate to a limited number of URLs.
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:
Create a new Windows Forms project and name it LimitedBrowser.
Add a ComboBox named cboUrls to the form and set its Dock
property to Top.
Add a WebBrowser control to the form.
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
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.
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
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.
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.
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>
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.
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.
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; }
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.
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.
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
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.
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.
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
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.
Develop an ASP.NET web service that enables the user to add two numbers.
Solution
Open Visual Studio 2010 and choose File
On the New Web Site dialog box, select ASP.NET Web Service and click OK.
In the App_Code/Service.vb
file, change the default reference http://tempuri.org
to something more relevant to your service.
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.
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.
Create a new website and add a service reference to a web service on your machine.
Solution
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.
Open a new instance of Visual Studio 2010 and create a new website project.
Right-click the name of the new project in the Solution Explorer and select Add Service Reference from the context menu.
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).
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.
WCF services are similar to web services, but they give developers more options for deployment and they support more data exchange protocols.
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.
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.
How do you access the methods of an ADO.NET data service?
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.
18.190.239.166