- •brief contents
- •about this book
- •The Windows Forms namespace
- •Part 1: Hello Windows Forms
- •Part 2: Basic Windows Forms
- •Part 3: Advanced Windows Forms
- •Who should read this book?
- •Conventions
- •Action
- •Result
- •Source code downloads
- •Author online
- •acknowledgments
- •about .NET
- •Casting the .NET
- •Windows Forms overview
- •about the cover illustration
- •Hello Windows Forms
- •1.1 Programming in C#
- •1.1.1 Namespaces and classes
- •1.1.2 Constructors and methods
- •1.1.3 C# types
- •1.1.4 The entry point
- •1.1.5 The Application class
- •1.1.6 Program execution
- •1.2 Adding controls
- •1.2.1 Shortcuts and fully qualified names
- •1.2.2 Fields and properties
- •1.2.3 The Controls property
- •1.3 Loading files
- •1.3.1 Events
- •1.3.2 The OpenFileDialog class
- •1.3.3 Bitmap images
- •1.4 Resizing forms
- •1.4.1 Desktop layout properties
- •1.4.2 The Anchor property
- •1.4.3 The Dock property
- •1.5 Recap
- •2.1 Programming with Visual Studio .NET
- •2.1.1 Creating a project
- •Action
- •Result
- •2.1.2 Executing a program
- •Action
- •Result
- •2.1.3 Viewing the source code
- •View the code generated by Visual Studio .NET
- •Action
- •Result
- •2.2 Adding controls
- •2.2.1 The AssemblyInfo file
- •Action
- •Results
- •2.2.2 Renaming a form
- •Action
- •Result
- •2.2.3 The Toolbox window
- •Action
- •Result
- •2.3 Loading files
- •2.3.1 Event handlers in Visual Studio .NET
- •Action
- •Result
- •2.3.2 Exception handling
- •Action
- •Result
- •Action
- •Results and Comments
- •2.4 Resizing forms
- •2.4.1 Assign the Anchor property
- •Action
- •Result
- •2.4.2 Assign the MinimumSize property
- •Action
- •Result
- •2.5 Recap
- •Basic Windows Forms
- •Menus
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •3.3 Click events
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •3.5 Context menus
- •Action
- •Result
- •Action
- •Result
- •3.6 Recap
- •Status bars
- •4.1 The Control class
- •4.2 The StatusBar class
- •Action
- •Result
- •Action
- •Result
- •4.3.1 Adding panels to a status bar
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •4.5 Recap
- •Reusable libraries
- •5.1 C# classes and interfaces
- •5.2 Class libraries
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •5.3 Interfaces revisited
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •5.4 Robustness issues
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Common file dialogs
- •Action
- •Results
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •6.3 Paint events
- •Action
- •Result
- •Action
- •Result
- •6.4 Context menus revisited
- •Action
- •Result
- •Action
- •Result
- •6.5 Files and paths
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •6.6 Save file dialogs
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •6.7 Open file dialogs
- •Action
- •Result
- •Action
- •Result
- •6.8 Recap
- •Drawing and scrolling
- •7.1 Form class hierarchy
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •7.4 Panels
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Dialog boxes
- •8.1 Message boxes
- •Action
- •Result
- •Action
- •Result
- •8.1.4 Creating A YesNoCancel dialog
- •Action
- •Result
- •Action
- •Result
- •8.2 The Form.Close method
- •8.2.1 The relationship between Close and Dispose
- •Action
- •Result
- •8.3 Modal dialog boxes
- •Action
- •Result
- •Action
- •Result
- •8.3.2 Preserving caption values
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Basic controls
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •9.1.2 Creating a derived form
- •Action
- •Result
- •9.2 Labels and text boxes
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •9.3.6 Adding AlbumEditDlg to our main form
- •Action
- •Result
- •Action
- •Result
- •9.4 Recap
- •List controls
- •10.1 List boxes
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •10.2 Multiselection list boxes
- •10.2.1 Enabling multiple selection
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •10.3 Combo boxes
- •Action
- •Result
- •Action
- •Result
- •10.4 Combo box edits
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •10.5 Owner-drawn lists
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •More controls
- •Action
- •Result
- •Action
- •Result
- •11.2 Tab pages
- •Action
- •Result
- •Action
- •Result
- •11.3.1 Dates and times
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •11.5 Recap
- •A .NET assortment
- •12.1 Keyboard events
- •Action
- •Result
- •Action
- •Result
- •12.2 Mouse events
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •12.3 Image buttons
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •12.4 Icons
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •12.5 Recap
- •Toolbars and tips
- •13.1 Toolbars
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •13.4.2 Creating tool tips
- •Action
- •Result
- •Action
- •Result
- •Advanced Windows Forms
- •List views
- •14.2 The ListView class
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •14.2.3 Populating a ListView
- •Action
- •Result
- •Action
- •14.3 ListView columns
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •14.6 Recap
- •Tree views
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •15.3 Dynamic tree nodes
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •15.4 Node selection
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •15.5 Fun with tree views
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Multiple document interfaces
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •16.3 Merged menus
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •16.4 MDI children
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •16.5 MDI child window management
- •Action
- •Result
- •Action
- •Result
- •16.6 Recap
- •Data binding
- •17.1 Data grids
- •Action
- •Result
- •Action
- •Result
- •17.2 Data grid customization
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Odds and ends .NET
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •18.2 Timers
- •Action
- •Result
- •Action
- •Result
- •18.3 Drag and drop
- •Action
- •Result
- •Action
- •Result
- •18.4 ActiveX controls
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •Action
- •Result
- •18.5 Recap
- •C# primer
- •A.1 C# programs
- •A.1.1 Assemblies
- •A.1.2 Namespaces
- •A.2 Types
- •A.2.1 Classes
- •A.2.2 Structures
- •A.2.3 Interfaces
- •A.2.4 Enumerations
- •A.2.5 Delegates
- •A.3 Language elements
- •A.3.1 Built-in types
- •A.3.2 Operators
- •A.3.3 Keywords
- •A.4 Special features
- •A.4.1 Exceptions
- •A.4.2 Arrays
- •A.4.3 Main
- •A.4.4 Boxing
- •A.4.5 Documentation
- •.NET namespaces
- •B.1 System.Collections
- •B.2 System.ComponentModel
- •B.3 System.Data
- •B.4 System.Drawing
- •B.5 System.Globalization
- •B.6 System.IO
- •B.7 System.Net
- •B.8 System.Reflection
- •B.9 System.Resources
- •B.10 System.Security
- •B.11 System.Threading
- •B.12 System.Web
- •B.13 System.Windows.Forms
- •B.14 System.XML
- •Visual index
- •C.1 Objects
- •C.2 Marshal by reference objects
- •C.3 Components
- •C.4 Common dialogs
- •C.7 Event data
- •C.8 Enumerations
- •For more information
- •bibliography
- •Symbols
- •Index
With our initial window in place, we are ready to display some album data in the window.
17.1.2DISPLAYING DATA IN A DATA GRID
Our main window in the MyAlbumData application contains a combo box and a data grid. Our ComboBox control will contain a list of the albums located in the default album directory, while our DataGrid control will display the contents of the selected album. This section will make the changes required for this behavior. Section 17.2 will look at customizing the information displayed by the grid.
Fortunately, our existing MyPhotoAlbum project can do most of the work here. The changes required are detailed in the following steps.
Set the version number of the MyAlbumData application to 17.1.
DISPLAY ALBUM DATA IN THE MYPHOTOALBUM APPLICATION
|
Action |
Result |
|
|
|
1 |
In the Solution Explorer window, |
|
|
add the MyPhotoAlbum project |
|
|
to the solution and reference it |
|
|
from the MyAlbumData project. |
|
|
|
|
2 |
At the top of the MainForm.cs |
using System.IO; |
|
code window, add a using |
using Manning.MyPhotoAlbum; |
|
statement for the new project |
|
|
and the System.IO namespace. |
|
|
|
|
3 |
Define a private PhotoAlbum |
private PhotoAlbum _album; |
|
field within the MainForm class. |
|
|
|
|
DATA GRIDS |
569 |
DISPLAY ALBUM DATA IN THE MYPHOTOALBUM APPLICATION (continued)
|
Action |
Result |
|
|
|
4 |
Override the OnLoad method to: |
protected override void OnLoad(EventArgs e) |
|
a. Add the version number to the |
{ |
|
Version ver |
|
|
title bar. |
= new Version(Application.ProductVersion); |
|
b. Initialize the photo album. |
Text = String.Format( |
|
"MyAlbumData {0:#}.{1:#}", |
|
|
c. Set the album file names to |
|
|
ver.Major, ver.Minor); |
|
|
appear in the ComboBox |
_album = new PhotoAlbum(); |
|
control. |
|
|
|
|
|
Note: The assignment of the |
cmbxAlbum.DataSource = Directory.GetFiles( |
|
DataSource property here is an |
PhotoAlbum.DefaultDir, "*.abm"); |
|
example of data binding. In this |
} |
|
|
|
|
case, we are binding the collec- |
|
|
tion of objects for the ComboBox |
|
|
control to an array of directory |
|
|
strings. |
|
|
|
|
5 |
Handle the SelectedIndex- |
private void cmbxAlbum_SelectedIndexChanged |
|
Changed event for the |
(object sender, System.EventArgs e) |
|
ComboBox object. |
{ |
|
|
|
|
|
|
6 |
In this handler, retrieve the string |
string albumFile |
|
selected in the combo box and |
= cmbxAlbum.SelectedItem.ToString(); |
|
dispose of any existing album. |
if (_album != null) |
|
|
|
|
|
_album.Dispose(); |
|
|
|
7 |
Open the selected album file. |
_album.Clear(); |
|
|
try |
|
|
{ |
|
|
_album.Open(albumFile); |
|
|
|
8 |
If the album opens successfully, |
gridPhotoAlbum.CaptionText = _album.Title; |
|
assign the album title as the |
} |
|
caption text for the DataGrid |
|
|
control. |
|
|
|
|
9 |
If the album cannot be opened, |
catch (Exception) |
|
clear the album and assign an |
{ |
|
error message as the caption |
_album.Clear(); |
|
gridPhotoAlbum.CaptionText |
|
|
text. |
|
|
= "Unable to open album"; |
|
|
|
} |
|
|
|
10 |
Bind the contents of the |
gridPhotoAlbum.SetDataBinding(null, null); |
|
resulting album to appear in the |
gridPhotoAlbum.SetDataBinding(_album, null); |
|
DataGrid control. |
} |
|
|
|
|
|
Note: Since the value of the _album field does not |
|
|
actually change, we force the data grid to reload the |
|
|
album data by binding it to null and then rebinding |
|
|
to our PhotoAlbum instance. We will do this a bit |
|
|
more elegantly later in the chapter. |
|
|
|
570 |
CHAPTER 17 DATA BINDING |
This code opens the selected album and assigns the title of the album to appear in the caption area of the data grid. The collection of photographs in the album is bound to the contents of the data grid. The result is shown in figure 17.3.
Figure 17.3
The DataGrid control supports two types of entries by default. Boolean values, such as the IsImageValid property, appear as check boxes. All other properties display the result of their ToString property as a text entry.
The caption area at the top of the control is assigned using the CaptionText property. In the figure, the title of the colors.abm album is “Lots of Colors” as is shown in the caption. The data source for the grid is assigned using the SetDataBinding method. This method has the following signature:
public void SetDataBinding(object dataSource, string dataMember);
The dataSource parameter is assigned to the DataSource property of the control, while the dataMember parameter is assigned to the DataMember property. In our application, the control recognizes our PhotoAlbum object as an IList interface containing a collection of Photograph objects. This is performed internally using the GetType method available on all object instances.
The properties of the Photograph object are determined internally using the members of the System.Reflection namespace. These properties are then used as the columns in the grid, and each Photograph in the album is presented as a row in the grid.
We will not discuss the System.Reflection namespace in detail here. This namespace permits .NET objects such as the DataGrid control to determine the type of object and members of that type at runtime. In this way our data grid can understand how the PhotoAlbum object is organized, and automatically create an appropriate grid structure.
Since the order of columns in the grid corresponds to the internal order of properties in the PhotoAlbum class, your columns might be ordered differently than is shown in figure 17.3. Also note that properties which only provide a get access method are treated as read-only, while properties with both a get and set access method are modifiable. As a result the Image and IsImageValid columns in our grid are read-only, while the Photographer and Notes columns can be modified. We will look at how to update the class with these changes shortly.
DATA GRIDS |
571 |
Back to our SetDataBinding method, there are a number of different classes that can serve as a source of data, depending on the type of C# interfaces they support. A summary of data sources for the DataGrid class is given in the following table.
Data sources for the data grid control
Interface |
Usage |
Notes |
|
|
|
IList |
A homogenous collection of objects. The |
This includes any simple array in C#, |
|
first item in the list determines the type. |
and all classes based on the Array |
|
The first property in that type is |
object. |
|
displayed as the only column when |
|
|
bound to a data grid. |
|
typed IList |
A typed collection, such as our |
Most notably, classes derived from |
|
PhotoAlbum class. The type returned by |
CollectionBase, such as our |
|
the Item property is used as the |
PhotoAlbum class. Other classes |
|
assigned type, and all properties in this |
with an indexer of a fixed type will |
|
type can be displayed in a data grid. |
also work here. |
|
These can be bound to a data grid only at |
|
|
run time. |
|
IList and |
With both interfaces available, the class |
Integrating a collection class with |
IComponent |
may appear in Visual Studio .NET in the |
Visual Studio .NET is beyond the |
|
component tray and be bound to a data |
scope of this book. A control can be |
|
grid at design time. |
added to the Toolbox using the |
|
|
Customize entry in the Toolbox |
|
|
window’s popup menu. This often |
|
|
requires members of the |
|
|
System.Windows.Forms.Design |
|
|
namespace to properly interact with |
|
|
the Windows Forms Designer and |
|
|
Property windows. |
IBindingList |
This interface permits two-way |
The DataView class in the |
|
notification of changes, both from the |
System.Data namespace |
|
control to the class and from the class to |
implements this interface, allowing a |
|
the control. |
data grid to update its contents when |
|
|
the underlying database is modified. |
IEditableObject |
Classes implementing this interface are |
The DataRowView class is a |
|
permitted to roll back, in a transaction- |
customized view of a row that |
|
oriented manner,a changes made to an |
supports transactional changes to the |
|
object. |
elements of the row. |
IDataErrorInfo |
Objects can offer custom error |
The DataRowView class supports this |
|
information that controls can bind to. |
interface as well in order to provide |
|
|
appropriate feedback in a DataGrid |
|
|
control when an error occurs. |
|
|
|
a. The term transaction indicates that a series of steps either fully completes or appears to never have happened. For example, when transferring money between bank accounts, you must debit the first account and then credit the second account. By making such a transfer transactional, you ensure that the first account is never debited without guaranteeing that the second account is also credited. Aborting an operation part-way through the required steps is said to roll back, or undo, the operation.
572 |
CHAPTER 17 DATA BINDING |