- •Contents at a Glance
- •Table of Contents
- •Acknowledgments
- •Introduction
- •Who This Book Is For
- •Finding Your Best Starting Point in This Book
- •Conventions and Features in This Book
- •Conventions
- •Other Features
- •System Requirements
- •Code Samples
- •Installing the Code Samples
- •Using the Code Samples
- •Support for This Book
- •Questions and Comments
- •Beginning Programming with the Visual Studio 2008 Environment
- •Writing Your First Program
- •Using Namespaces
- •Creating a Graphical Application
- •Chapter 1 Quick Reference
- •Understanding Statements
- •Identifying Keywords
- •Using Variables
- •Naming Variables
- •Declaring Variables
- •Working with Primitive Data Types
- •Displaying Primitive Data Type Values
- •Using Arithmetic Operators
- •Operators and Types
- •Examining Arithmetic Operators
- •Controlling Precedence
- •Using Associativity to Evaluate Expressions
- •Associativity and the Assignment Operator
- •Incrementing and Decrementing Variables
- •Declaring Implicitly Typed Local Variables
- •Chapter 2 Quick Reference
- •Declaring Methods
- •Specifying the Method Declaration Syntax
- •Writing return Statements
- •Calling Methods
- •Specifying the Method Call Syntax
- •Applying Scope
- •Overloading Methods
- •Writing Methods
- •Chapter 3 Quick Reference
- •Declaring Boolean Variables
- •Using Boolean Operators
- •Understanding Equality and Relational Operators
- •Understanding Conditional Logical Operators
- •Summarizing Operator Precedence and Associativity
- •Using if Statements to Make Decisions
- •Understanding if Statement Syntax
- •Using Blocks to Group Statements
- •Cascading if Statements
- •Using switch Statements
- •Understanding switch Statement Syntax
- •Following the switch Statement Rules
- •Chapter 4 Quick Reference
- •Using Compound Assignment Operators
- •Writing while Statements
- •Writing for Statements
- •Understanding for Statement Scope
- •Writing do Statements
- •Chapter 5 Quick Reference
- •Coping with Errors
- •Trying Code and Catching Exceptions
- •Handling an Exception
- •Using Multiple catch Handlers
- •Catching Multiple Exceptions
- •Using Checked and Unchecked Integer Arithmetic
- •Writing Checked Statements
- •Writing Checked Expressions
- •Throwing Exceptions
- •Chapter 6 Quick Reference
- •The Purpose of Encapsulation
- •Controlling Accessibility
- •Working with Constructors
- •Overloading Constructors
- •Understanding static Methods and Data
- •Creating a Shared Field
- •Creating a static Field by Using the const Keyword
- •Chapter 7 Quick Reference
- •Copying Value Type Variables and Classes
- •Understanding Null Values and Nullable Types
- •Using Nullable Types
- •Understanding the Properties of Nullable Types
- •Using ref and out Parameters
- •Creating ref Parameters
- •Creating out Parameters
- •How Computer Memory Is Organized
- •Using the Stack and the Heap
- •The System.Object Class
- •Boxing
- •Unboxing
- •Casting Data Safely
- •The is Operator
- •The as Operator
- •Chapter 8 Quick Reference
- •Working with Enumerations
- •Declaring an Enumeration
- •Using an Enumeration
- •Choosing Enumeration Literal Values
- •Choosing an Enumeration’s Underlying Type
- •Working with Structures
- •Declaring a Structure
- •Understanding Structure and Class Differences
- •Declaring Structure Variables
- •Understanding Structure Initialization
- •Copying Structure Variables
- •Chapter 9 Quick Reference
- •What Is an Array?
- •Declaring Array Variables
- •Creating an Array Instance
- •Initializing Array Variables
- •Creating an Implicitly Typed Array
- •Accessing an Individual Array Element
- •Iterating Through an Array
- •Copying Arrays
- •What Are Collection Classes?
- •The ArrayList Collection Class
- •The Queue Collection Class
- •The Stack Collection Class
- •The Hashtable Collection Class
- •The SortedList Collection Class
- •Using Collection Initializers
- •Comparing Arrays and Collections
- •Using Collection Classes to Play Cards
- •Chapter 10 Quick Reference
- •Using Array Arguments
- •Declaring a params Array
- •Using params object[ ]
- •Using a params Array
- •Chapter 11 Quick Reference
- •What Is Inheritance?
- •Using Inheritance
- •Base Classes and Derived Classes
- •Calling Base Class Constructors
- •Assigning Classes
- •Declaring new Methods
- •Declaring Virtual Methods
- •Declaring override Methods
- •Understanding protected Access
- •Understanding Extension Methods
- •Chapter 12 Quick Reference
- •Understanding Interfaces
- •Interface Syntax
- •Interface Restrictions
- •Implementing an Interface
- •Referencing a Class Through Its Interface
- •Working with Multiple Interfaces
- •Abstract Classes
- •Abstract Methods
- •Sealed Classes
- •Sealed Methods
- •Implementing an Extensible Framework
- •Summarizing Keyword Combinations
- •Chapter 13 Quick Reference
- •The Life and Times of an Object
- •Writing Destructors
- •Why Use the Garbage Collector?
- •How Does the Garbage Collector Work?
- •Recommendations
- •Resource Management
- •Disposal Methods
- •Exception-Safe Disposal
- •The using Statement
- •Calling the Dispose Method from a Destructor
- •Making Code Exception-Safe
- •Chapter 14 Quick Reference
- •Implementing Encapsulation by Using Methods
- •What Are Properties?
- •Using Properties
- •Read-Only Properties
- •Write-Only Properties
- •Property Accessibility
- •Understanding the Property Restrictions
- •Declaring Interface Properties
- •Using Properties in a Windows Application
- •Generating Automatic Properties
- •Initializing Objects by Using Properties
- •Chapter 15 Quick Reference
- •What Is an Indexer?
- •An Example That Doesn’t Use Indexers
- •The Same Example Using Indexers
- •Understanding Indexer Accessors
- •Comparing Indexers and Arrays
- •Indexers in Interfaces
- •Using Indexers in a Windows Application
- •Chapter 16 Quick Reference
- •Declaring and Using Delegates
- •The Automated Factory Scenario
- •Implementing the Factory Without Using Delegates
- •Implementing the Factory by Using a Delegate
- •Using Delegates
- •Lambda Expressions and Delegates
- •Creating a Method Adapter
- •Using a Lambda Expression as an Adapter
- •The Form of Lambda Expressions
- •Declaring an Event
- •Subscribing to an Event
- •Unsubscribing from an Event
- •Raising an Event
- •Understanding WPF User Interface Events
- •Using Events
- •Chapter 17 Quick Reference
- •The Problem with objects
- •The Generics Solution
- •Generics vs. Generalized Classes
- •Generics and Constraints
- •Creating a Generic Class
- •The Theory of Binary Trees
- •Building a Binary Tree Class by Using Generics
- •Creating a Generic Method
- •Chapter 18 Quick Reference
- •Enumerating the Elements in a Collection
- •Manually Implementing an Enumerator
- •Implementing the IEnumerable Interface
- •Implementing an Enumerator by Using an Iterator
- •A Simple Iterator
- •Chapter 19 Quick Reference
- •What Is Language Integrated Query (LINQ)?
- •Using LINQ in a C# Application
- •Selecting Data
- •Filtering Data
- •Ordering, Grouping, and Aggregating Data
- •Joining Data
- •Using Query Operators
- •Querying Data in Tree<TItem> Objects
- •LINQ and Deferred Evaluation
- •Chapter 20 Quick Reference
- •Understanding Operators
- •Operator Constraints
- •Overloaded Operators
- •Creating Symmetric Operators
- •Understanding Compound Assignment
- •Declaring Increment and Decrement Operators
- •Implementing an Operator
- •Understanding Conversion Operators
- •Providing Built-In Conversions
- •Creating Symmetric Operators, Revisited
- •Adding an Implicit Conversion Operator
- •Chapter 21 Quick Reference
- •Creating a WPF Application
- •Creating a Windows Presentation Foundation Application
- •Adding Controls to the Form
- •Using WPF Controls
- •Changing Properties Dynamically
- •Handling Events in a WPF Form
- •Processing Events in Windows Forms
- •Chapter 22 Quick Reference
- •Menu Guidelines and Style
- •Menus and Menu Events
- •Creating a Menu
- •Handling Menu Events
- •Shortcut Menus
- •Creating Shortcut Menus
- •Windows Common Dialog Boxes
- •Using the SaveFileDialog Class
- •Chapter 23 Quick Reference
- •Validating Data
- •Strategies for Validating User Input
- •An Example—Customer Information Maintenance
- •Performing Validation by Using Data Binding
- •Changing the Point at Which Validation Occurs
- •Chapter 24 Quick Reference
- •Querying a Database by Using ADO.NET
- •The Northwind Database
- •Creating the Database
- •Using ADO.NET to Query Order Information
- •Querying a Database by Using DLINQ
- •Creating and Running a DLINQ Query
- •Deferred and Immediate Fetching
- •Joining Tables and Creating Relationships
- •Deferred and Immediate Fetching Revisited
- •Using DLINQ to Query Order Information
- •Chapter 25 Quick Reference
- •Using Data Binding with DLINQ
- •Using DLINQ to Modify Data
- •Updating Existing Data
- •Adding and Deleting Data
- •Chapter 26 Quick Reference
- •Understanding the Internet as an Infrastructure
- •Understanding Web Server Requests and Responses
- •Managing State
- •Understanding ASP.NET
- •Creating Web Applications with ASP.NET
- •Building an ASP.NET Application
- •Understanding Server Controls
- •Creating and Using a Theme
- •Chapter 27 Quick Reference
- •Comparing Server and Client Validations
- •Validating Data at the Web Server
- •Validating Data in the Web Browser
- •Implementing Client Validation
- •Chapter 28 Quick Reference
- •Managing Security
- •Understanding Forms-Based Security
- •Implementing Forms-Based Security
- •Querying and Displaying Data
- •Understanding the Web Forms GridView Control
- •Displaying Customer and Order History Information
- •Paging Data
- •Editing Data
- •Updating Rows Through a GridView Control
- •Navigating Between Forms
- •Chapter 29 Quick Reference
- •What Is a Web Service?
- •The Role of SOAP
- •What Is the Web Services Description Language?
- •Nonfunctional Requirements of Web Services
- •The Role of Windows Communication Foundation
- •Building a Web Service
- •Creating the ProductsService Web Service
- •Web Services, Clients, and Proxies
- •Talking SOAP: The Easy Way
- •Consuming the ProductsService Web Service
- •Chapter 30 Quick Reference
Chapter 24 Performing Validation |
491 |
4.In the Gender group box, click the Female radio button.
Again, the checkTitleAndGender method generates an exception, and the Female radio button appears highlighted with a red border. Rest the mouse pointer on the Female combo box, and verify that the ScreenTip text “The gender must match the title of the customer” appears.
5.On the File menu, click Save.
A message box appears, displaying the title (“Mr”) and the gender (“Female”) of the customer. Although the form contains erroneous and missing data (you have not entered a name), you can still save the data!
6.Click OK, and then type a name in the foreName and lastName text boxes, but do not click away from the lastName text box.
7.On the File menu, click Save again.
The message box now includes the first name of the customer but not the last name. This happens because the lastName text box on the form has not lost the focus. Remember from earlier that data binding validation for a text box occurs only when the
user clicks another control on the form. The same applies to the data itself; by default, it is copied to the customerDetails object only when the text box loses the focus. In fact, it is the act of copying the data from the form to the customerDetails object that triggers the validation.
8.Click OK, and then click the Title combo box. Set the title to “Mrs”. On the File menu, click Save.
This time, the message box displays the first name and last name of the customer. Also, although the title (“Mrs”) and gender (“Female”) now match, the radio button still flags an error.
9.Click OK, close the application, and return to Visual Studio 2008.
Changing the Point at Which Validation Occurs
The issue with the Customer Information application is that the validation is performed at the wrong time, is inconsistently applied, and does not actually prevent the user from saving inconsistent data. You just need an alternative approach to handling the validation. The solution is to check the user’s input only when the user saves the data. This way, you can ensure that the user has finished entering all the data and that it is consistent. If there are any problems, you can display an error message and prevent the data from be-
ing saved until the problems have been corrected. In the following exercise, you will modify the Customer Information application to postpone validation until the user attempts to save the customer information.
492 |
Part IV Working with Windows Applications |
Validate data explicitly
1.Return to the Design View window displaying CustomerForm.xaml. In the XAML pane, modify the binding for the title combo box and set the UpdateSourceTrigger property to “Explicit”, as shown in bold type here:
<ComboBox ... Name=”title” ...>
...
<ComboBox.Text>
<Binding Source=”{StaticResource customerData}” Path=”Title” Converter=”{StaticResource titleConverter}” UpdateSourceTrigger=”Explicit” >
...
</Binding>
</ComboBox.Text>
</ComboBox>
The UpdateSourceTrigger property governs when the information entered by the user is sent back to the underlying Customer object and validated. Setting this property to “Explicit” postpones this synchronization until your application explicitly performs it by
using code.
2.Modify the bindings for the foreName and lastName text boxes to set the
UpdateSourceTrigger property to “Explicit”:
<TextBox ... Name=”foreName” ... > <TextBox.Text>
<Binding Source=”{StaticResource customerData}” Path=”ForeName”
UpdateSourceTrigger=”Explicit” >
...
</Binding>
</TextBox.Text>
</TextBox>
...
<TextBox ... Name=”lastName” ... > <TextBox.Text>
<Binding Source=”{StaticResource customerData}” Path=”LastName”
UpdateSourceTrigger=”Explicit” >
...
</Binding>
</TextBox.Text>
</TextBox>
The application is not going to check consistency between the title and gender of the
customer until the user saves the customer information. If the validation rule for the Title property passes, there is no need to validate the Gender property. Similarly, if the validation rule for the Title property fails, there is no need to examine the Gender property. In other words, the validation rule for the Gender radio buttons on the form is now redundant, so remove it. To do so, remove the Binding.ValidationRules and ExceptionValidationRule elements from the bindings for the male and female radio buttons. Do not set the UpdateSourceTrigger property of the bindings to “Explicit”.
Chapter 24 Performing Validation |
493 |
3.Return to the Code and Text Editor window displaying the CustomerForm.xaml.cs file. In the rebuildBinding method, locate the statement that adds the validation rule to the binding and comment it out as shown in bold type here:
private Binding rebuildBinding(string parameter)
{
...
// binding.ValidationRules.Add(new ExceptionValidationRule());
...
}
4.In the saveCustomer_Click method, add the statements shown here in bold type to the start of the method:
private void saveCustomer_Click(object sender, RoutedEventArgs e)
{
BindingExpression titleBe = this.title.GetBindingExpression(ComboBox.TextProperty);
BindingExpression foreNameBe = this.foreName.GetBindingExpression(TextBox.TextProperty);
BindingExpression lastNameBe = this.lastName.GetBindingExpression(TextBox.TextProperty);
...
}
These statements create BindingExpression objects for each of the three controls with
binding validation rules. In an earlier exercise in this chapter, you saw that you can use a BindingExpression object to ensure that the data displayed on the form is synchronized with the data in the Customer object by calling the UpdateTarget method. The BindingExpression class also provides the UpdateSource method, which synchronizes
data the other way around, sending the values in the bound properties of controls on the form back to the Customer object. When this occurs, the data will also be validated.
5.Add the following statements shown in bold type to the saveCustomer_Click method after the code you added in the preceding step:
private void saveCustomer_Click(object sender, RoutedEventArgs e)
{
...
titleBe.UpdateSource();
foreNameBe.UpdateSource();
lastNameBe.UpdateSource();
...
}
These statements update the properties in the Customer object with the values entered
by the user on the form, and they validate the data as they do so. Notice that there is no need to update the Gender property manually because you did not set the UpdateSourceTrigger property to “Explicit” for the binding for the radio buttons; the
Gender property is still updated automatically.
494 Part IV Working with Windows Applications
The BindingExpression class provides a property called HasError that indicates whether the UpdateSource method was successful or whether it caused an exception.
6.Add the code shown here in bold type to the saveCustomer_Click method to test the HasError property of each BindingExpression object and display a message if the validation fails. Move the original code that displays the customer details to the else part of the if statement.
private void saveCustomer_Click(object sender, RoutedEventArgs e)
{
...
if (titleBe.HasError || foreNameBe.HasError || lastNameBe.HasError)
{
MessageBox.Show(“Please correct errors”, “Not Saved”);
}
else
{
Binding customerBinding =
BindingOperations.GetBinding(this.title, ComboBox.TextProperty); Customer customer = customerBinding.Source as Customer; MessageBox.Show(customer.ToString(), “Saved”);
}
}
Test the application again
1.On the Debug menu, click Start Without Debugging to build and run the application.
2.When the Customer Details form appears, set the Title combo box to “Mrs”. Notice that the combo box is not highlighted because it has not yet been validated.
3.On the File menu, click Save.
A message box should appear with the message “Please correct errors,” and the Title and Name fields on the form should be highlighted. This is because the value in the Title combo box does not match the gender, and you have left the Name fields blank. If you rest the mouse on the fields highlighted with the red border, the ScreenTips display the reason for the error message.
4.Click OK to close the message box.
5.Click the Female radio button, and then enter a first name and last name for the customer.
Notice that the highlighting of the controls with errors does not disappear.
6.On the File menu, click Save again.
This time, the data is complete and consistent. A message box should appear, displaying the full details of the customer, and the highlighting on the form disappears.
7.Click OK, and exit the application.