- •Using Your Sybex Electronic Book
- •Acknowledgments
- •Contents at a Glance
- •Introduction
- •Who Should Read This Book?
- •How About the Advanced Topics?
- •The Structure of the Book
- •How to Reach the Author
- •The Integrated Development Environment
- •The Start Page
- •Project Types
- •Your First VB Application
- •Making the Application More Robust
- •Making the Application More User-Friendly
- •The IDE Components
- •The IDE Menu
- •The Toolbox Window
- •The Solution Explorer
- •The Properties Window
- •The Output Window
- •The Command Window
- •The Task List Window
- •Environment Options
- •A Few Common Properties
- •A Few Common Events
- •A Few Common Methods
- •Building a Console Application
- •Summary
- •Building a Loan Calculator
- •How the Loan Application Works
- •Designing the User Interface
- •Programming the Loan Application
- •Validating the Data
- •Building a Math Calculator
- •Designing the User Interface
- •Programming the MathCalculator App
- •Adding More Features
- •Exception Handling
- •Taking the LoanCalculator to the Web
- •Working with Multiple Forms
- •Working with Multiple Projects
- •Executable Files
- •Distributing an Application
- •VB.NET at Work: Creating a Windows Installer
- •Finishing the Windows Installer
- •Running the Windows Installer
- •Verifying the Installation
- •Summary
- •Variables
- •Declaring Variables
- •Types of Variables
- •Converting Variable Types
- •User-Defined Data Types
- •Examining Variable Types
- •Why Declare Variables?
- •A Variable’s Scope
- •The Lifetime of a Variable
- •Constants
- •Arrays
- •Declaring Arrays
- •Initializing Arrays
- •Array Limits
- •Multidimensional Arrays
- •Dynamic Arrays
- •Arrays of Arrays
- •Variables as Objects
- •So, What’s an Object?
- •Formatting Numbers
- •Formatting Dates
- •Flow-Control Statements
- •Test Structures
- •Loop Structures
- •Nested Control Structures
- •The Exit Statement
- •Summary
- •Modular Coding
- •Subroutines
- •Functions
- •Arguments
- •Argument-Passing Mechanisms
- •Event-Handler Arguments
- •Passing an Unknown Number of Arguments
- •Named Arguments
- •More Types of Function Return Values
- •Overloading Functions
- •Summary
- •The Appearance of Forms
- •Properties of the Form Control
- •Placing Controls on Forms
- •Setting the TabOrder
- •VB.NET at Work: The Contacts Project
- •Anchoring and Docking
- •Loading and Showing Forms
- •The Startup Form
- •Controlling One Form from within Another
- •Forms vs. Dialog Boxes
- •VB.NET at Work: The MultipleForms Project
- •Designing Menus
- •The Menu Editor
- •Manipulating Menus at Runtime
- •Building Dynamic Forms at Runtime
- •The Form.Controls Collection
- •VB.NET at Work: The DynamicForm Project
- •Creating Event Handlers at Runtime
- •Summary
- •The TextBox Control
- •Basic Properties
- •Text-Manipulation Properties
- •Text-Selection Properties
- •Text-Selection Methods
- •Undoing Edits
- •VB.NET at Work: The TextPad Project
- •Capturing Keystrokes
- •The ListBox, CheckedListBox, and ComboBox Controls
- •Basic Properties
- •The Items Collection
- •VB.NET at Work: The ListDemo Project
- •Searching
- •The ComboBox Control
- •The ScrollBar and TrackBar Controls
- •The ScrollBar Control
- •The TrackBar Control
- •Summary
- •The Common Dialog Controls
- •Using the Common Dialog Controls
- •The Color Dialog Box
- •The Font Dialog Box
- •The Open and Save As Dialog Boxes
- •The Print Dialog Box
- •The RichTextBox Control
- •The RTF Language
- •Methods
- •Advanced Editing Features
- •Cutting and Pasting
- •Searching in a RichTextBox Control
- •Formatting URLs
- •VB.NET at Work: The RTFPad Project
- •Summary
- •What Is a Class?
- •Building the Minimal Class
- •Adding Code to the Minimal Class
- •Property Procedures
- •Customizing Default Members
- •Custom Enumerations
- •Using the SimpleClass in Other Projects
- •Firing Events
- •Shared Properties
- •Parsing a Filename String
- •Reusing the StringTools Class
- •Encapsulation and Abstraction
- •Inheritance
- •Inheriting Existing Classes
- •Polymorphism
- •The Shape Class
- •Object Constructors and Destructors
- •Instance and Shared Methods
- •Who Can Inherit What?
- •Parent Class Keywords
- •Derived Class Keyword
- •Parent Class Member Keywords
- •Derived Class Member Keyword
- •MyBase and MyClass
- •Summary
- •On Designing Windows Controls
- •Enhancing Existing Controls
- •Building the FocusedTextBox Control
- •Building Compound Controls
- •VB.NET at Work: The ColorEdit Control
- •VB.NET at Work: The Label3D Control
- •Raising Events
- •Using the Custom Control in Other Projects
- •VB.NET at Work: The Alarm Control
- •Designing Irregularly Shaped Controls
- •Designing Owner-Drawn Menus
- •Designing Owner-Drawn ListBox Controls
- •Using ActiveX Controls
- •Summary
- •Programming Word
- •Objects That Represent Text
- •The Documents Collection and the Document Object
- •Spell-Checking Documents
- •Programming Excel
- •The Worksheets Collection and the Worksheet Object
- •The Range Object
- •Using Excel as a Math Parser
- •Programming Outlook
- •Retrieving Information
- •Recursive Scanning of the Contacts Folder
- •Summary
- •Advanced Array Topics
- •Sorting Arrays
- •Searching Arrays
- •Other Array Operations
- •Array Limitations
- •The ArrayList Collection
- •Creating an ArrayList
- •Adding and Removing Items
- •The HashTable Collection
- •VB.NET at Work: The WordFrequencies Project
- •The SortedList Class
- •The IEnumerator and IComparer Interfaces
- •Enumerating Collections
- •Custom Sorting
- •Custom Sorting of a SortedList
- •The Serialization Class
- •Serializing Individual Objects
- •Serializing a Collection
- •Deserializing Objects
- •Summary
- •Handling Strings and Characters
- •The Char Class
- •The String Class
- •The StringBuilder Class
- •VB.NET at Work: The StringReversal Project
- •VB.NET at Work: The CountWords Project
- •Handling Dates
- •The DateTime Class
- •The TimeSpan Class
- •VB.NET at Work: Timing Operations
- •Summary
- •Accessing Folders and Files
- •The Directory Class
- •The File Class
- •The DirectoryInfo Class
- •The FileInfo Class
- •The Path Class
- •VB.NET at Work: The CustomExplorer Project
- •Accessing Files
- •The FileStream Object
- •The StreamWriter Object
- •The StreamReader Object
- •Sending Data to a File
- •The BinaryWriter Object
- •The BinaryReader Object
- •VB.NET at Work: The RecordSave Project
- •The FileSystemWatcher Component
- •Properties
- •Events
- •VB.NET at Work: The FileSystemWatcher Project
- •Summary
- •Displaying Images
- •The Image Object
- •Exchanging Images through the Clipboard
- •Drawing with GDI+
- •The Basic Drawing Objects
- •Drawing Shapes
- •Drawing Methods
- •Gradients
- •Coordinate Transformations
- •Specifying Transformations
- •VB.NET at Work: Plotting Functions
- •Bitmaps
- •Specifying Colors
- •Defining Colors
- •Processing Bitmaps
- •Summary
- •The Printing Objects
- •PrintDocument
- •PrintDialog
- •PageSetupDialog
- •PrintPreviewDialog
- •PrintPreviewControl
- •Printer and Page Properties
- •Page Geometry
- •Printing Examples
- •Printing Tabular Data
- •Printing Plain Text
- •Printing Bitmaps
- •Using the PrintPreviewControl
- •Summary
- •Examining the Advanced Controls
- •How Tree Structures Work
- •The ImageList Control
- •The TreeView Control
- •Adding New Items at Design Time
- •Adding New Items at Runtime
- •Assigning Images to Nodes
- •Scanning the TreeView Control
- •The ListView Control
- •The Columns Collection
- •The ListItem Object
- •The Items Collection
- •The SubItems Collection
- •Summary
- •Types of Errors
- •Design-Time Errors
- •Runtime Errors
- •Logic Errors
- •Exceptions and Structured Exception Handling
- •Studying an Exception
- •Getting a Handle on this Exception
- •Finally (!)
- •Customizing Exception Handling
- •Throwing Your Own Exceptions
- •Debugging
- •Breakpoints
- •Stepping Through
- •The Local and Watch Windows
- •Summary
- •Basic Concepts
- •Recursion in Real Life
- •A Simple Example
- •Recursion by Mistake
- •Scanning Folders Recursively
- •Describing a Recursive Procedure
- •Translating the Description to Code
- •The Stack Mechanism
- •Stack Defined
- •Recursive Programming and the Stack
- •Passing Arguments through the Stack
- •Special Issues in Recursive Programming
- •Knowing When to Use Recursive Programming
- •Summary
- •MDI Applications: The Basics
- •Building an MDI Application
- •Built-In Capabilities of MDI Applications
- •Accessing Child Forms
- •Ending an MDI Application
- •A Scrollable PictureBox
- •Summary
- •What Is a Database?
- •Relational Databases
- •Exploring the Northwind Database
- •Exploring the Pubs Database
- •Understanding Relations
- •The Server Explorer
- •Working with Tables
- •Relationships, Indices, and Constraints
- •Structured Query Language
- •Executing SQL Statements
- •Selection Queries
- •Calculated Fields
- •SQL Joins
- •Action Queries
- •The Query Builder
- •The Query Builder Interface
- •SQL at Work: Calculating Sums
- •SQL at Work: Counting Rows
- •Limiting the Selection
- •Parameterized Queries
- •Calculated Columns
- •Specifying Left, Right, and Inner Joins
- •Stored Procedures
- •Summary
- •How About XML?
- •Creating a DataSet
- •The DataGrid Control
- •Data Binding
- •VB.NET at Work: The ViewEditCustomers Project
- •Binding Complex Controls
- •Programming the DataAdapter Object
- •The Command Objects
- •The Command and DataReader Objects
- •VB.NET at Work: The DataReader Project
- •VB.NET at Work: The StoredProcedure Project
- •Summary
- •The Structure of a DataSet
- •Navigating the Tables of a DataSet
- •Updating DataSets
- •The DataForm Wizard
- •Handling Identity Fields
- •Transactions
- •Performing Update Operations
- •Updating Tables Manually
- •Building and Using Custom DataSets
- •Summary
- •An HTML Primer
- •HTML Code Elements
- •Server-Client Interaction
- •The Structure of HTML Documents
- •URLs and Hyperlinks
- •The Basic HTML Tags
- •Inserting Graphics
- •Tables
- •Forms and Controls
- •Processing Requests on the Server
- •Building a Web Application
- •Interacting with a Web Application
- •Maintaining State
- •The Web Controls
- •The ASP.NET Objects
- •The Page Object
- •The Response Object
- •The Request Object
- •The Server Object
- •Using Cookies
- •Handling Multiple Forms in Web Applications
- •Summary
- •The Data-Bound Web Controls
- •Simple Data Binding
- •Binding to DataSets
- •Is It a Grid, or a Table?
- •Getting Orders on the Web
- •The Forms of the ProductSearch Application
- •Paging Large DataSets
- •Customizing the Appearance of the DataGrid Control
- •Programming the Select Button
- •Summary
- •How to Serve the Web
- •Building a Web Service
- •Consuming the Web Service
- •Maintaining State in Web Services
- •A Data-Driven Web Service
- •Consuming the Products Web Service in VB
- •Summary
THE SERIALIZER CLASS 521
sList.Add(14, “item 5”) sList.Add(18, “item 1”) sList.Add(12, “item 7”) sList.Add(19, “item 0”) sList.Add(13, “item 6”) While SLEnum.MoveNext
Console.WriteLine(“Key = “ & SLEnum.Key.Tostring & “, Value= “ & _ SLEnum.Value.ToString & “, Cos(key) = “ & _ Math.Cos(CType(SLEnum.Key, Double)))
End While
If you execute these statements, they will generate the following output:
Key = 16, Value= item 3, Cos(key) = -0.9576594803233847
Key = 10, Value= item 9, Cos(key) = -0.8390715290764524
Key = 15, Value= item 4, Cos(key) = -0.7596879128588213
Key = 17, Value= item 2, Cos(key) = -2.7516333805159693E-01
Key = 11, Value= item 8, Cos(key) = 4.4256979880507854E-03
Key = 14, Value= item 5, Cos(key) = 0.1367372182078336
Key = 18, Value= item 1, Cos(key) = 0.6603167082440802
Key = 12, Value= item 7, Cos(key) = 0.8438539587324921
Key = 13, Value= item 6, Cos(key) = 0.9074467814501962
Key = 19, Value= item 0, Cos(key) = 0.9887046181866692
Once you have declared a custom comparer, you can use it with the BinarySearch method as well. The binary search algorithm uses consecutive comparisons to locate an item in a sorted collection. If the custom comparer is in place, it simply calls your Compare() function to perform the comparisons and locate the item in the collection. The form of the BinarySearch method that uses a custom comparer to locate an item is
BinarySearch(object, comparer())
where object is the item you’re looking for and comparer is the name of the custom comparer. For every collection that uses a custom comparer for its Sort method, you must call this form of the BinarySearch method.
In Chapter 8 we created a class to represent shapes and added a method to calculate the area of each shape. You can create an ArrayList of Shape objects and write your own comparer to sort the elements of the ArrayList according to the area of each shape.
The Serialization Class
You have seen how the various collections of VB.NET store items, how to access their elements, and even how to sort and search the collections. The last piece of information you need before you can use collections in your applications to store large sets of data is how to store collections to disk files. In the last section of this chapter, you’ll learn how to do this so you can reuse a collection at a later time. What good is it to create a long collection, if your application can’t retrieve from a disk file in another session?
None of the collections exposes a Save or a similarly named method. Fortunately, there’s a mechanism that can store arbitrary objects to disk: the Serialization class. This class exposes the Serialize
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
522 Chapter 11 STORING DATA IN COLLECTIONS
method, which saves an object to disk. The Deserialize method does the opposite: it reads a file created by the Serialize method and re-creates the original object. The Serialization class is a complicated one, but in this book I will discuss its Serialize and Deserialize methods, which you can use to persist your collection (and custom data types) to disk. When it comes to saving objects to disk (or even exchange them with other applications), the proper term is persist, which basically means to make an entity like an object, or variable, available to the application between sessions.
Serializing Individual Objects
To serialize an object, you must call the Serialize method of the System.Runtime.Serialization
.Formatters.Binary object. First, declare an object of this type with a statement like the following:
Dim BFormatter As New BinaryFormatter()
To avoid fully qualifying the BinaryFormatter class, import the class into your project with the following statement:
Imports System.Runtime.Serialization.Formatters.BinaryFormatter
The BinaryFormatter class persists objects in binary format. You can also persist objects in text format, using the SoapFormatter. The SoapFormatter persists the objects in XML format, which is quite verbose and the corresponding files are considerably lengthier. To use the SoapFormatter object, you must add a reference to the following .NET component through the Add Reference dialog box:
System.Runtime.Serialization.Formatters.Soap
Notice that this isn’t a class you can import; you must add a reference to the class. After that, you can declare a SoapFormatter variable with the following statement:
Dim formatter As Soap.SoapFormatter
If you’re wondering where the name of this class comes from, SOAP is an acronym for Simple Object Access Protocol. This is a protocol for accessing objects over HTTP—in other words, it’s a protocol that allows the encoding of objects in text format. The SOAP protocol was designed to enable distributed computing over the Internet, and it’s used with Web services. So, if SOAP can be used to access objects over the Internet, why not use it to persist objects in text format?
The methods of the BinaryFormatter and SoapFormatter are equivalent, so I will use the BinaryFormatter in the examples of this section. At the end of the section, I will show the code behind the menu of the WordFrequencies project, which persists the HashTable with the words and their frequencies to both binary and text format.
The syntax of the Serialize method is
BFormatter.Serialize(stream, object)
where stream is a variable that represents a stream and object is the object you want to serialize. Since we want to persist our objects to disk files, the stream argument represents a stream to a binary file.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
THE SERIALIZER CLASS 523
The File object and its methods are discussed in detail in Chapter 13; here, I will only explain briefly the statements we’ll use to store data to a disk file and read it back. The following statements create such a Stream object:
Dim saveFile As FileStream
saveFile = File.Create(“C:\SHAPES.BIN”)
The saveFile variable represents the stream to a specific file on the disk, and the Create method of the same variable creates a stream to this file.
After you have set up the Stream and BinaryFormatter objects, you can call the Serialize method to serialize any object. To serialize a Rectangle object, for example, use the following statements:
Dim R As New Rectangle(0, 0 , 100, 100)
BFormatter.Serialize(saveFile, R)
The event handler in Listing 11.20 persists two Rectangle objects to the Shapes.bin file in the root folder. The file’s extension can be anything. Since the file is binary, I’ve used the BIN extension:
Listing 11.20: Serializing Distinct Objects
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Dim R1 As New Rectangle()
R1.X = 1
R1.Y = 1 R1.Size.Width = 10 R1.Size.Height = 20
Dim R2 As New Rectangle() R2.X = 10
R2.Y = 10 R2.Size.Width = 100 R2.Size.Height = 200
Dim saveFile As FileStream
saveFile = File.Create(“C:\SHAPES.BIN”) Dim formatter As BinaryFormatter formatter = New BinaryFormatter() formatter.Serialize(saveFile, R1) formatter.Serialize(saveFile, R2) saveFile.Close()
End Sub
Notice that the Serialize method serializes a single object at a time. To save the two rectangles, the code calls the Serialize method once for each rectangle. To serialize multiple objects with a single statement, you must create a collection, append all the objects to the collection, and then serialize the collection itself, as explained in the following section.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
524 Chapter 11 STORING DATA IN COLLECTIONS
Serializing a Collection
Serializing a collection is quite similar to serializing any single object. The second argument to the Serialize method is the object you want to serialize, and this object can be anything, including a collection. To demonstrate the serialization of an ArrayList, we’ll modify the previous code a little, so that instead of persisting individual items, it will persist an entire collection. Declare the two Rectangle objects as before, but this time append them to an ArrayList collection. Then add a color value to the collection, as shown in Listing 11.21, which serializes an ArrayList collection to the file
C:\ShapesColors.bin.
Listing 11.21: Serializing a Collection
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click Dim R1 As New Rectangle()
R1.X = 1
R1.Y = 1 R1.Width = 10 R1.Height = 20
Dim R2 As New Rectangle() R2.X = 10
R2.Y = 10 R2.Width = 100 R2.Height = 200
Dim shapes As New ArrayList() shapes.Add(R1) shapes.Add(R2) shapes.Add(Color.Chartreuse)
shapes.Add(Color.DarkKhaki.GetBrightness)
shapes.Add(Color.DarkKhaki.GetHue)
shapes.Add(Color.DarkKhaki.GetSaturation) Dim saveFile As FileStream
saveFile = File.OpenWrite(“C:\ShapesColors.bin”) saveFile.Seek(0, SeekOrigin.End)
Dim formatter As BinaryFormatter = New BinaryFormatter() formatter.Serialize(saveFile, shapes)
saveFile.Close()
MsgBox(“ArrayList serialized successfully”) End Sub
The last three Add methods add the components of another color to the collection. Instead of adding the color as is, we’re adding three color components, from which we can reconstruct the color Color.DarkKhaki. Then we proceed to save the entire collection to a file using the same statements as before. The difference is that we don’t call the Serialize method for each object. We call it once and pass the entire ArrayList as argument.
If you open the ShapesColors.bin file with a text editor (start Notepad and drop the file on its window), you will see that most of the file contains binary information—most of the characters are
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |