1. Trang chủ
  2. » Công Nghệ Thông Tin

Manning Windows Forms Programming (phần 13) ppt

50 225 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Manning Windows Forms Programming (phần 13) ppt
Trường học University of Sample Education
Chuyên ngành Windows Forms Programming
Thể loại Lecture slide
Năm xuất bản 2023
Thành phố Sample City
Định dạng
Số trang 50
Dung lượng 580,85 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

D ATA GRIDS 567.NET Table 17.1 DataGrid class The DataGrid class represents a control that displays a collection of data as a grid of rows and columns.. DataMember Gets or sets which li

Trang 1

Shows the name of each column.

The ListView class discussed in chapter 14 can also be used to present a table ofinformation The Windows Forms namespace provides explicit classes to representthe rows and columns in a list view As you may recall, each item, or row, in the list isrepresented by the ListViewItem class instance, and each column by a ListView- SubItem instance and is presented based on a ColumnHeader instance

As illustrated by figure 17.2, the DataGrid class takes a somewhat differentapproach The contents of the grid are contained in a single collection, such as anarray, a photo album, or a database table Classes exist to configure the style in whichthe provided data is displayed, including colors, column ordering, and other proper-ties We will discuss the details of these style classes later in the chapter

Figure 17.2 This chapter will discuss many of the terms and classes related to data grids.

Trang 2

D ATA GRIDS 567

.NET Table 17.1 DataGrid class

The DataGrid class represents a control that displays a collection of data as a grid of rows and columns The data displayed and the style in which it is presented is fully configurable This class is part of the System.Windows.Forms namespace, and inherits from the Control class See NET Table 4.1 on page 104 for a list of members inherited by this class.

CaptionVisible Gets or sets whether the caption is visible

Other properties related to this and other grid areas are also provided.

CurrentCell Gets or sets a DataGridCell structure

representing the cell in the grid that has the focus.

CurrentRowIndex Gets or sets the index of the selected row DataMember Gets or sets which list in the assigned data

source should be displayed in the grid DataSource Gets or sets the source of data for the grid Item Gets or sets the value of a cell This property is

the C# indexer for this class.

ReadOnly Gets or sets whether the grid is in read-only

BeginEdit Attempts to begin an edit on the grid.

HitTest Returns location information within the grid of

a specified point on the screen This works much like the HitTest method in the MonthCalendar class.

SetDataBinding Assigns the DataSource and DataMember

properties to the given values at run time Unselect Deselects a specified row.

Public Events

CurrentCellChanged Occurs when the current cell has changed DataSourceChanged Occurs when a new data source is assigned Navigate Occurs when the user navigates to a new

table.

Scroll Occurs when the user scrolls the data grid.

Trang 3

17.1.1 C REATING THE M Y A LBUM D ATA PROJECT

While the DataGrid class includes numerous members for customizing the ance and behavior of the control, it is possible to create a very simple grid with only afew lines of code We will begin with such an application, and enhance it over thecourse of the chapter

appear-The following table lays out the creation and initial layout of our new application

C REATE THE M Y A LBUM D ATA PROJECT

1 Create a new project and solution in

Visual Studio NET called

“MyAlbumData.”

The new solution is shown in the Solution Explorer window, with the default Form1.cs [Design] window displayed.

2 Rename the Form1.cs file and

related class file to our standard MainForm class and assign some initial settings for this form.

3 Drag a Label , ComboBox ,

DataGrid , and Button control onto the form Arrange these controls as shown in the graphic.

4 Create a Click event handler for

the Close button to shut down the application.

private void btnClose_Click (object sender, System.EventArgs e) {

Close();

}

Settings Property Value

(Name) MainForm Size 450, 300 Text MyAlbumData

Settings Control Property Value

Label Text &Album

ComboBox (Name) cmbxAlbum

Anchor Top, Left, Right

DataGrid

(Name)

gridPhoto-Album Anchor Top, Bottom,

Left, Right

Button

(Name) btnClose Anchor Bottom, Right Text &Close

Trang 4

D ATA GRIDS 569

With our initial window in place, we are ready to display some album data in thewindow

17.1.2 D ISPLAYING DATA IN A DATA GRID

Our main window in the MyAlbumData application contains a combo box and a datagrid Our ComboBox control will contain a list of the albums located in the defaultalbum directory, while our DataGrid control will display the contents of the selectedalbum This section will make the changes required for this behavior Section 17.2 willlook 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.

D ISPLAY ALBUM DATA IN THE M Y P HOTO A LBUM APPLICATION

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

code window, add a using statement for the new project and the System.IO namespace.

using System.IO;

using Manning.MyPhotoAlbum;

3 Define a private PhotoAlbum

field within the MainForm class.

private PhotoAlbum _album;

Trang 5

4 Override the OnLoad method to:

a Add the version number to the title bar.

b Initialize the photo album.

c Set the album file names to appear in the ComboBox control.

Note: The assignment of the

DataSource property here is an 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.

protected override void OnLoad(EventArgs e) {

Version ver = new Version(Application.ProductVersion); Text = String.Format(

"MyAlbumData {0:#}.{1:#}", ver.Major, ver.Minor);

_album = new PhotoAlbum();

cmbxAlbum.DataSource = Directory.GetFiles( PhotoAlbum.DefaultDir, "*.abm");

}

5 Handle the

SelectedIndex-Changed event for the ComboBox object.

private void cmbxAlbum_SelectedIndexChanged (object sender, System.EventArgs e) {

6 In this handler, retrieve the string

selected in the combo box and dispose of any existing album.

string albumFile = cmbxAlbum.SelectedItem.ToString();

if (_album != null) _album.Dispose();

7 Open the selected album file _album.Clear();

try { _album.Open(albumFile);

8 If the album opens successfully,

assign the album title as the caption text for the DataGrid control.

gridPhotoAlbum.CaptionText = _album.Title; }

9 If the album cannot be opened,

clear the album and assign an error message as the caption text.

catch (Exception) {

_album.Clear();

gridPhotoAlbum.CaptionText = "Unable to open album";

}

10 Bind the contents of the

resulting album to appear in the DataGrid control.

gridPhotoAlbum.SetDataBinding(null, null); gridPhotoAlbum.SetDataBinding(_album, null); }

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.

Trang 6

D ATA GRIDS 571

This code opens the selected album and assigns the title of the album to appear in thecaption area of the data grid The collection of photographs in the album is bound tothe contents of the data grid The result is shown in figure 17.3

The caption area at the top of the control is assigned using the CaptionText erty In the figure, the title of the colors.abm album is “Lots of Colors” as is shown inthe caption The data source for the grid is assigned using the SetDataBindingmethod 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 ourapplication, the control recognizes our PhotoAlbum object as an IList interfacecontaining a collection of Photograph objects This is performed internally usingthe GetType method available on all object instances

The properties of the Photograph object are determined internally using the bers of the System.Reflection namespace These properties are then used as the col-umns in the grid, and each Photograph in the album is presented as a row in the grid

mem-We will not discuss the System.Reflection namespace in detail here Thisnamespace 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 stand how the PhotoAlbum object is organized, and automatically create an appro-priate grid structure

under-Since the order of columns in the grid corresponds to the internal order of erties in the PhotoAlbum class, your columns might be ordered differently than isshown in figure 17.3 Also note that properties which only provide a get accessmethod are treated as read-only, while properties with both a get and set accessmethod are modifiable As a result the Image and IsImageValid columns in our gridare read-only, while the Photographer and Notes columns can be modified We willlook at how to update the class with these changes shortly

prop-Figure 17.3 The DataGrid control sup- ports 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 prop- erty as a text entry.

Trang 7

Back to our SetDataBinding method, there are a number of different classesthat 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

IList A homogenous collection of objects The

first item in the list determines the type

The first property in that type is displayed as the only column when bound to a data grid.

This includes any simple array in C#, and all classes based on the Array object.

typed IList A typed collection, such as our

PhotoAlbum class The type returned by the Item property is used as the assigned type, and all properties in this type can be displayed in a data grid

These can be bound to a data grid only at run time.

Most notably, classes derived from CollectionBase , such as our PhotoAlbum class Other classes with an indexer of a fixed type will also work here.

IList and

IComponent

With both interfaces available, the class may appear in Visual Studio NET in the component tray and be bound to a data grid at design time.

Integrating a collection class with Visual Studio NET is beyond the scope of this book A control can be 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

notification of changes, both from the control to the class and from the class to the control.

The DataView class in the System.Data namespace implements this interface, allowing a data grid to update its contents when the underlying database is modified.

IEditableObject Classes implementing this interface are

permitted to roll back, in a oriented manner, a changes made to an object.

transaction-a. The term transaction indicates that a series of steps either fully completes or appears to never have

hap-pened 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.

The DataRowView class is a customized view of a row that supports transactional changes to the elements of the row.

IDataErrorInfo Objects can offer custom error

information that controls can bind to.

The DataRowView class supports this interface as well in order to provide appropriate feedback in a DataGrid control when an error occurs.

Trang 8

D ATA GRID CUSTOMIZATION 573

For our purposes, we will continue to use the typed IList interface supported byour PhotoAlbum class Later in the chapter we will add support for the IEdit- ableObject interface in order to properly save modifications made in our data grid.The next section discusses various ways of customizing what appears in the grid

17.2 D ATA GRID CUSTOMIZATION

One of the obvious drawbacks of letting NET do all the work in laying out the tents of a data grid is that we have no control over the selection and order of columns

con-to appear in the grid In this section we will look at how con-to cuscon-tomize the contents of

a data grid for a particular data source using table and column styles This will enable

us to build the application shown in figure 17.4

In our current application we display a single kind of table, namely one based on thePhotoAlbum class In general, the data displayed in a data grid may vary depending

on the actions of the user For example, just as our ListView control in chapter 14displayed both albums and photographs, we could create an AlbumCollectionclass derived from CollectionBase to contain the set of albums located in a givendirectory We could then use this class to display both album files and the contents ofalbums in our data grid

More commonly, a data grid is filled with information from a database, whichincludes one or more tables An employee database at a company might have one tablecontaining department information, another table containing the employees assigned

to each department, and another containing the projects each employee is assigned to

A single data grid could display all three types of tables based on a set of options, and

it would be nice to customize the appearance of each type of table

Figure 17.4 This data grid displays only certain properties of photographs, and the size and content of each column are somewhat customized compared with the application

in the previous section.

Trang 9

The TableStyles property in the DataGrid class supports this notion of figuring the appearance of multiple tables This property contains a collection of Data- GridTableStyleobjects, each of which describes the configuration for a table thatmight be displayed by the grid The DataGridTableStyleclass, in turn, provides aGridColumnStylesproperty that contains a collection of DataGridColumnStyleobjects We will discuss each of these classes separately.

con-17.2.1 C USTOMIZING TABLE STYLES

The DataGridTableStyle class permits a custom style for a specific type of table

to be defined Many of the members of this class are duplicates of similar members inthe DataGrid class The members of the active table style always override the defaultsettings for the data grid A summary of this class appears in NET Table 17.2

.NET Table 17.2 DataGridTableStyle class

The DataGridTableStyle class represents the style in which to display a particular table that can appear in a DataGrid control It configures not only the general properties for the table but also the individual columns that should appear in the table This class is part of the System.Win- dows.Forms namespace, and inherits from the System.ComponentModel.Component class.

Public Properties

AllowSorting Gets or sets whether sorting is allowed on the grid when this

DataGridTableStyle is used.

Color

AlternatingBack-Gets or sets the background color for alternating rows in the grid when this DataGridTableStyle is used.

DataGrid Gets or sets the DataGrid control containing this style GridColumn-

Styles

Gets or sets the collection of DataGridColumnStyle objects

to use for the grid when this style is used.

LinkColor Gets or sets the color of link text to use in the grid when this

style is used.

MappingName Gets or sets the name used to associate this table style with

a specific data source For a data source based on an IList interface, the name of the list is specified, as in

myList.GetType().Name For a data source based on a DataSet instance, a valid table name in the data set should

be specified.

ReadOnly Gets or sets whether columns can be edited in the grid when

this style is used.

Width

RowHeader-Gets or sets the width of row headers in the grid when this style is used.

Public Methods

BeginEdit Requests an edit operation on a row in the grid.

EndEdit Requests an end to an edit operation in the grid.

ResetBackColor Resets the BackColor property to its default value A

number of other reset methods exist with a similar purpose.

Public Events

Changed

AllowSorting-Occurs when the AllowSorting property value changes A number of other changed events exist with a similar purpose.

Trang 10

D ATA GRID CUSTOMIZATION 575

There are two keys to understanding the DataGridTableStyle class The first isthe MappingName property When a new source of data is assigned to a DataGridcontrol, the list of table styles is examined to locate a style whose MappingName set-ting matches the name of the table If one is found, then that style is used to displaythe grid If no match is found, then the default settings for the grid control are used

It is an error to assign identical mapping names to multiple styles within the samedata grid

The second key to understanding this class is the GridColumnStyles property.This property is a collection of DataGridColumnStyle objects and specifies theselection and order of columns to display in the grid If the GridColumnStylesproperty is null, then the default set of columns is displayed

We can use the DataGridTableStyle class to modify the appearance of ourDataGrid control when a PhotoAlbum is displayed We will make the very simplechange of providing an alternating background color for the table The steps requiredare presented in the following table

Set the version number of the MyAlbumData application to 17.2

This very simple change causes the application to display as is shown in figure 17.5

Of course, the AlternatingBackColor and RowHeaderWidth properties areavailable in the DataGrid class and can be set explicitly for this class Assigning them

in a table style uses these properties only when a matching table name is displayed, inthis case a PhotoAlbum object

Note that our choice of light gray may not work very well with some user’s desktopcolors You can use an alternate color if you prefer, or a system color such as System- Colors.ControlLight In your own applications, make sure you carefully select

P ROVIDE A CUSTOM TABLE STYLE WHEN A P HOTO A LBUM IS DISPLAYED

1 In the MainForm.cs code

window, create a table style instance in the OnLoad method.

Note: A table style can also be

created in the [Design] window

by clicking on the … button in

the TableStyles property

Here we elect to create the table style by hand.

protected override void OnLoad(EventArgs e) {

// Table style for PhotoAlbum data source DataGridTableStyle albumStyle

= new DataGridTableStyle();

2 Configure the new style for a

PhotoAlbum table with an alternating background color of LightGray

albumStyle.MappingName = "PhotoAlbum"; albumStyle.AlternatingBackColor = Color.LightGray;

albumStyle.RowHeaderWidth = 15;

3 Assign the new style to the

existing DataGrid control.

// Assign the table style to the data grid gridPhotoAlbum.TableStyles.Add(albumStyle); }

Trang 11

color choices for settings such as this, and use system settings where possible coding a specific color such as we do here is not typically recommended, since differentusers may configure their desktops to appear using different sets of conflicting colors.

Hard-Note that the assignment of the MappingName is critical here Using a name otherthan PhotoAlbum would have no effect on our table since the name of the tablewould not match the mapping name of the table style

Of course, our table still uses the default set of columns since we have not yetassigned any column styles to the GridColumnStyles property Customizing thecolumns in our table is our next topic

Now that we know how to customize the properties of a table, let’s look at how tocustomize the columns that appear in the table The DataGridColumnStyle class

is used for this purpose, and is summarized in NET Table 17.3 This is an abstractclass from which various types of columns are derived The NET Framework cur-rently provides classes to represent boolean and text columns, namely the Data- GridBoolColumn and DataGridTextBoxColumn classes

Figure 17.5 This figure shows an alternating background color of light gray

to present a ledger-like appearance.

Trang 12

D ATA GRID CUSTOMIZATION 577

The order in which columns are assigned to a table style determines the order inwhich they will appear in the data grid We will use this feature to extend the tablestyle we created for our form to display only a subset of the available columns.The code to make this change is detailed in the following table Note that thiscode uses the DataGridBoolColumnand DataGridTextBoxColumnclasses Wewill discuss these classes in more detail in a moment

.NET Table 17.3 DataGridColumnStyle class

The DataGridColumnStyle class represents a specific column that should appear when a specific style table is displayed in a DataGrid control This object is typically contained within

a DataGridTableStyle object, and indicates the position and style for the corresponding umn when a table of the specified type is displayed This class is part of the System.Win- dows.Forms namespace, and inherits from the System.ComponentModel.Component class.

col-A DataGridColumnStyle object cannot be instantiated, as this is an abstract class The DataGridBoolColumn and DataGridTextBoxColumn classes derived from this class are used to represent a column of boolean or textual values, respectively Custom column styles derived from this class may also be created.

Public Properties

Alignment Gets or sets the alignment of data within the column DataGridTableStyle Gets the table style containing this column style HeaderText Gets or sets the header text for this column when the

associated table style is used.

MappingName Gets or sets the name used to associate this column

style with a specific data value in an associated data source For an IList data source, a valid property name

in the list should be specified For a DataSet data source, a valid column name in the associated table should be provided

NullText Gets or sets the text that is displayed when the column

contains a null reference.

PropertyDescriptor Gets or sets the PropertyDescriptor object

containing attributes of the data displayed by this column style.

ReadOnly Gets or sets whether to treat the column as read-only Width Gets or sets the width in pixels for this column.

Public Methods

ResetHeaderText Resets the HeaderText property to its default value,

which is a null reference.

Public Events

AlignmentChanged Occurs when the Alignment property for the column

style changes.

FontChanged Occurs when the column’s font changes A number of

other changed events exist with a similar purpose.

Trang 13

This adds the new column styles to the existing table style object When a data source

of type PhotoAlbum is displayed, the new styles specify which columns should

C USTOMIZE THE COLUMNS TO APPEAR IN THE DATA GRID

1 Locate the OnLoad method in the

MainForm.cs code window.

protected override void OnLoad(EventArgs e) {

// Table style for PhotoAlbum data source

// Column styles for PhotoAlbum source DataGridColumnStyle captionCol = new DataGridTextBoxColumn();

How-to

Use the class specified for each property in the following table.

DataGridColumnStyle validCol = new DataGridBoolColumn();

validCol.MappingName = "IsImageValid"; validCol.HeaderText = "Valid?";

validCol.ReadOnly = true;

validCol.Width = 30;

DataGridTextBoxColumn dateCol = new DataGridTextBoxColumn();

dateCol.MappingName = "DateTaken";

dateCol.HeaderText = "Date Taken";

dateCol.Alignment = HorizontalAlignment.Center;

dateCol.Format = "d";

dateCol.Width = 80;

DataGridColumnStyle photographerCol = new DataGridTextBoxColumn();

photographerCol.MappingName ="Photographer"; photographerCol.HeaderText = "Photographer"; photographerCol.Width = 100;

DataGridColumnStyle fileNameCol = new DataGridTextBoxColumn();

fileNameCol.MappingName = "FileName"; fileNameCol.HeaderText = "Image File Name"; fileNameCol.ReadOnly = true;

fileNameCol.Width = 200;

4 Add the new column styles to

the GridColumnStyles property

of the existing table style object.

validCol, dateCol, photographerCol, fileNameCol });

// Assign the table style to the data grid gridPhotoAlbum.TableStyles.Add(albumStyle); }

Column Style Classes Property Class

IsImageValid BoolColumn DateTaken TextBoxColumn Photographer TextBoxColumn FileName TextBoxColumn

Trang 14

D ATA GRID CUSTOMIZATION 579

appear and how they should look For example, the column style based on the ageValid property is as follows:

DataGridColumnStyle validCol = new DataGridBoolColumn();

The remaining column styles are all based on the DataGridTextBoxColumnclass A summary of this class appears in NET Table 17.4 Of particular note is thedate column, which uses the Format property in this class to display the date value

as a short date string The Alignment property from the base class is also assignedfor this column in order to center the displayed date

DataGridTextBoxColumn dateCol = new DataGridTextBoxColumn();

.NET Table 17.4 DataGridTextBoxColumn class

The DataGridTextBoxColumn class represents a data grid column style for string data This

class hosts, or manages within a cell of the DataGrid control, a TextBox instance to support editing of string values within the table This class is part of the System.Windows.Forms namespace, and inherits from the DataGridColumnStyle class See NET Table 17.3 for a list

of members inherited from this class.

Public Properties

Format Gets or sets a string specifying how text should be

formatted within the cell.

FormatInfo Gets or sets an IFormatProvider interface that is

used to interpret the Format setting.

TextBox Gets the TextBox object hosted by this column style

This object is an instance of the DataGridTextBox class, which is derived from TextBox

Trang 15

The DataGridBoolColumn class has an alternate set of properties appropriate forboolean columns Check out the NET documentation for detailed information onthis class.

TRY IT! Modify the MappingName setting for the table style to use a name other

than the "PhotoAlbum" string Verify that the DataGrid displays the bum data in the default format shown in section 17.1

al-If you are feeling ambitious, create the AlbumCollection class tioned earlier in the chapter This class should derive from the Collec- tionBase class and encapsulate a set of PhotoAlbum objects You cancopy much of the code from the PhotoAlbum class implementation bymodifying the use of Photograph to use PhotoAlbum instead The de-fault constructor should use the PhotoAlbum.DefaultDir value Youcan also add a constructor that accepts a directory name Modify the MyAl-bumData application to use this class to display a collection of PhotoAlbum

men-objects Create a second DataGridTableStyle object to configure how

an AlbumCollection object should look as opposed to our style for the

PhotoAlbum object Add this new style to the TableStyles property forthe grid, and verify that the correct table style displays based on the type ofdata source assigned to the control

As we mentioned earlier, some of our columns are configured as read-only while some

of them can be edited You can see this in the existing application by clicking on aneditable cell and modifying its contents Unfortunately, changing the contents of acell has no effect at the moment since we are not saving the modified values in ouralbum file Saving such changes properly requires the use of the IEditableObjectinterface, which is our next topic

There are three areas for discussion here The first is the way in which data gridssupport editing of their contents The second is how to enable such support in thePhotograph objects displayed by our table The third is how to actually save the datainto an album file once such editing is possible We will discuss each topic separately

17.3.1 T HE IE DITABLE O BJECT INTERFACE

The editing of rows in a grid is handled by the DataGrid control directly using thediscovered properties associated with our PhotoAlbum object When the userchanges a caption, the Caption property is called automatically by the grid to

Trang 16

E DITABLE OBJECTS 581

update the corresponding Photograph object with the new value Similarly, whenthe photographer is changed, the Photographer property is called The controleven handles the DateTaken property gracefully so that an invalid date value is neverassigned to the object

The problem is that our updated Photograph objects are never saved in the responding album file A quick and easy solution would be to forcibly save the albumwhenever a new album is selected For example, the SelectedIndexChanged eventhandler could be altered as follows, with the modified lines in bold

private void cmbxAlbum_SelectedIndexChanged

(object sender, System.EventArgs e)

{

string albumFile = cmbxAlbum.SelectedItem.ToString();

// Forcibly save previous album – not our approach

Implementing this change requires the IEditableObject interface, rized in NET Table 17.5 This interface defines a mechanism for modifying an object

summa-in a transactional manner, so that either all changes to an object are made or none ofthe changes are made This is especially important in databases, where the fields of arow may be dependent on one another, or in multi-user environments, where differentusers may wish to update the same object at the same time For example, in a customerorder database, you would not want to modify the shipping method without alsoupdating the shipping costs The IEditableObject interface is used to ensure thatthis happens

As an example, the DataRowView class in the System.Data namespace ports the IEditableObject interface to ensure transactional update to the rows in

sup-a dsup-atsup-absup-ase We sup-are not building sup-a dsup-atsup-absup-ase here, but we would like to updsup-ate the toAlbum object in a consistent manner The IEditableObject interface provides

Pho-a wPho-ay for us to do this over the course of this section

Trang 17

17.3.2 S UPPORTING THE IE DITABLE O BJECT INTERFACE

Looking at the Photograph class, there are four modifiable properties These are theCaption, Photographer, DateTaken, and Notes properties As a result, these arethe properties we need to consider in our IEditableObject implementation Thefollowing table summarizes the implementation of the required methods:

Our implementation will not be something you would present at a computer scienceconvention In particular, a Photograph object can be modified without using ouredit methods, which kind of defeats the whole purpose of the interface The code pre-sented here is intended to illustrate the behavior of these methods and indicate howthey are used by the DataGrid control

With this excuse in mind, let’s see how to support the editable object interfacefor our Photograph class

.NET Table 17.5 IEditableObject interface

The IEditableObject interface represents an interface for performing transactional tions on an object This interface is used by various NET classes such as the Windows Forms DataGrid control to allow an object to track and enforce transactional behavior This interface

opera-is part of the System.ComponentModel namespace.

Public Methods

BeginEdit Initiates an edit operation on an object.

CancelEdit Discards any changes made since the last edit operation

began, including any new objects added to the list with the IBindingList.AddNew method.

EndEdit Finalizes an edit operation Any changes made since the

last edit operation began are made permanent in the object, including any new objects added with the IBindingList.AddNew method.

Implementation of IEditableObject methods for the Photograph class

BeginEdit Should record the existing values of the modifiable properties and

place the photo in an editing state.

CancelEdit Should reinstate the recorded values from BeginEdit , and place the

photo in a nonediting state.

EndEdit Should discard the recorded values from BeginEdit , note if the

photo has been changed, and place the photo in a nonediting state.

Trang 18

E DITABLE OBJECTS 583

Set the version number of the MyPhotoAlbum library to 17.3.

S UPPORT THE IE DITABLE O BJECT INTERFACE IN THE P HOTOGRAPH CLASS

1 In the Photograph.cs code

window, indicate that we will use members of the System.ComponentModel namespace.

using System.ComponentModel;

2 Add IEditableObject to the

list of supported interfaces for this class.

public class Photograph : IDisposable,

IEditableObject

{ .

3 Add internal fields to track when

the object is in an editable state

or has been modified.

private bool _modified;

private bool _editing;

4 Initialize these fields in the

constructor.

public Photograph(string fileName) {

_modified = false;

_editing = false;

}

5 Reset these values when the

photograph is saved into a StreamWriter object.

public void Write(StreamWriter sw) {

_modified = false;

_editing = false;

}

6 Add internal fields to record the

existing values of the four modifiable properties.

private string _editCaption;

private string _editPhotographer;

private DateTime _editDateTaken;

private string _editNotes;

7 Implement the BeginEdit

method.

How-to

If editing is not already enabled, record the current values and enable editing.

Note: Ideally, we would permit

nesting of these calls In this example we will avoid this addi- tional complexity.

public void BeginEdit() {

if (!_editing) {

8 Implement the CancelEdit

method.

How-to

If editing is enabled, restore the recorded values and disable editing.

public void CancelEdit() {

if (_editing) {

Trang 19

The IEditableObject interface is now fully implemented Another useful change

in our library is the ability to identify if a PhotoAlbum, and not just a Photograph,has been modified We can do this by continuing the previous steps to add aHasEdits method in the PhotoAlbum class

The MyPhotoAlbum library is ready to go Make sure the library compiles with noerrors The next step is to make use of these changes in our MyAlbumData applica-tion This is taken up in the next section

17.3.3 U SING EDITABLE OBJECTS

Typically, you do not actually use the editable object methods directly These are usedinternally by Windows Forms as required for the task at hand In this case, our Data- Grid control automatically recognizes that our PhotoAlbum object supports thisinterface, and calls BeginEdit whenever a user initiates a change to a row in the grid

If a user cancels an edit by pressing the Esc key, then CancelEdit is called When the

9 Implement the EndEdit

method.

How-to

If editing is enabled, record whether the data has been modified and disable editing.

public void EndEdit() {

if (_editing) {

_modified |= ((Caption != _editCaption) || (Photographer != _editPhotographer) || (DateTaken != _editDateTaken) || (Notes != _editNotes));

_editing = false;

} }

10 Also add a HasEdits property to

report whether the object has been modified.

public bool HasEdits {

get { return _modified; } }

A DD A H AS E DITS PROPERTY TO THE P HOTO A LBUM CLASS

11 In the PhotoAlbum.cs code

window, Implement a HasEdits method in this class.

How-to

Use the Photograph.HasEdits method to determine the appropriate result.

public bool HasEdits {

get { foreach (Photograph p in this) {

if (p.HasEdits) return true;

} // No edits found return false;

} }

Trang 20

E DITABLE OBJECTS 585

user finishes an edit by pressing the Enter key or selecting an alternate row, theEndEdit method is invoked The EndEdit method makes the changes to the objectpermanent within the object itself

In most applications, there is an operation or class that coordinates the ory version of an object with the permanent version of an object In our application,the in-memory version is our PhotoAlbum class, while the permanent version is ouralbum file The Save method updates the album file with the version in memory,while the Open method fills the in-memory version with the recorded version in thealbum file

in-mem-This is true in the System.Data namespace as well While we have avoided cussing this namespace in any real depth, it is useful to understand how the classes inthis namespace relate to our discussion The abstract DataAdaptor class is the coor-dinator between the in-memory version of the database, typically a DataSet instance,and the permanent version is an external database The DataAdaptor class provides

dis-a Fill method to populate a DataSet with the external values, and an Updatemethod to save modifications in the DataSet into the external database

For our purposes, we have provided the HasEdits method in our in-memoryobjects in order to identify whether any changes must be saved into the album file Wecan do this in the SelectedIndexChanged event handler before the new album isbound to our data grid

The following table details the steps required to save our PhotoAlbum instanceinto its associated album file:

Set the version number of the MyAlbumData application to 17.3.

S AVE A MODIFIED ALBUM

1 In the MainForm.cs window,

create a new SaveChanges method to store any changes to the displayed album into the album file.

private void SaveChanges() {

if (_album.HasEdits) {

DialogResult result = MessageBox.Show( "Do you wish to save your changes " + "to the album \'" + _album.Title + "\'?",

"Save Changes?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

if (result == DialogResult.Yes) _album.Save();

} }

Trang 21

With these modifications, our edits are now saved Compile and run to verify that theapplication works as advertised.

More NET Additional information on the DataGrid control is available in the NET

documentation and in various sample programs freely available on the ternet One such example is the CdrCatalog program built by AndrewSkowronski that is available at http://cdrcatalog.sourceforge.net/ This pro-gram manages offline media, such as a collection of recordable compactdiscs, and makes use of a number of Windows Forms classes in addition tothe DataGrid control The data source used by this application is a

In-DataSet object loaded from a local XML file

17.4 S IMPLE DATA BINDING

Binding data to a data grid is referred to as complex data binding, since multiple values

are bound to a single control Complex data binding also refers to binding objects to

a list control, such as a list box or combo box For example, if we had actually mented the AlbumCollection class I keep mentioning to contain an array of Pho- toAlbum objects, then the line to assign the DataSource for our combo box couldinstead be written as:

cmbxAlbum.DataSource = myAlbumCollection;

cmbxAlbum.DataMember = "FileName";

This would display the collection of PhotoAlbum objects in the tion variable in the cmbxAlbum combo box, using the FileName property as the

myAlbumCollec-2 Use this new method when the

user selects a new album in the ComboBox control.

private void cmbxAlbum_SelectedIndexChanged (object sender, System.EventArgs e) {

string albumFile = cmbxAlbum.SelectedItem.ToString();

if (_album != null) {

3 Also make sure any changes are

saved when the application exits.

protected override void OnClosing (CancelEventArgs e)

{ SaveChanges();

base.OnClosing(e);

}

Trang 22

S IMPLE DATA BINDING 587

name to display The result would be the same as that which currently appears in ourapplication This type of binding to a list control can also be done with databaseobjects, such as binding the entries in a ListBox control to the set of customernames found in one column of a database table

Simple data binding is used for binding single property values to a specific data

source This type of binding is supported by the Control class directly, and is fore inherited by and available in all controls in Windows Forms The concepts andtechniques for so-called simple data binding are fairly identical to those we havealready discussed for the DataGrid control

there-In this section we will alter our application to permit some simple data binding

to a photo album We will see how to perform simple binding; update bound controlsdynamically, including the image associated with a photograph; and save changes tobound controls

17.4.1 A LTERING THE M Y A LBUM D ATA APPLICATION

Before we get into the details of exactly how simple data binding is performed, let’swhip through some changes to our MyAlbumData application in preparation for thisdiscussion The change we will make is to place our existing DataGrid controlwithin a TabPage object, and add a new tab to display the Photograph informa-tion for an album one photo at a time Figure 17.6 shows the modified application

we will build throughout this and the next few sections

Figure 17.6 These controls on the Photo tab are bound to their

corre-sponding values in a Photograph object.

Trang 23

In this section we will simply move our existing DataGrid control into an Albumtab, and create a Photo tab containing the controls shown in the figure The follow-ing steps implement this change.

Set the version number of the MyAlbumData application to 17.4.

C REATE THE CONTROLS WITHIN A TAB CONTROL OBJECT

1 In the MainForm.cs [Design] window,

alter the Size property for the form to

be 450×350.

2 Move the existing DataGrid control to

exist within a tab page.

How-to

a Create a tab control containing two tab pages.

b Set their properties as shown.

c Move the data grid into the Album tab page, and set its Dock property

to Fill

Settings Control Property Value

TabControl (Name) tcMain

Anchor Top, Bottom,

Left, Right TabPage (Album) (Name) tabAlbum

TabPage (Photo) (Name) tabPhoto

Text Photo

Trang 24

S IMPLE DATA BINDING 589

3 Create and position the controls for

the Photo tab page as shown in the graphic.

Note: In the rather long Settings table

here, the Label controls are not shown For these controls, use the default name, the text shown in the graphic, and the same Anchor prop- erty as the related control.

Also note that all TextBox controls should have their Text property set to

an empty string.

Note: When assigning the Anchor property, you may find it easier to first create and posi- tion the controls and then use the following technique:

a Select a group of related controls by ging the mouse over a region of the form.

drag-b Assign the Anchor property for all controls

at once.

Settings Control Property Value

FileName (Name) txtFileName

ReadOnly True PictureBox (Name) pboxPhoto

Anchor Top, Bottom,

Left, Right BorderStyle FixedSingle Prev (Name) btnPrev

Anchor Bottom, Left Text Pre&v

Anchor Bottom, Right Text Nex&t Caption (Name) txtCaption

Anchor Top, Right Photo-

grapher

(Name)

txtPhoto-grapher Anchor Top, Right Date Taken (Name) dtpDateTaken

Anchor Top, Right Format Short Notes (Name) txtNotes

Anchor Top, Bottom,

Right Multiline True

Trang 25

That took a bit of work As we mentioned earlier in the book, you can reduce theamount of time spent drawing forms in Visual Studio by sketching out your controls

on paper before using Visual Studio While not illustrated in these pages, I really didsketch the Photo tab page by hand before creating this page in Visual Studio NET.With our controls defined, we are ready for our data binding discussion

17.4.2 P ERFORMING SIMPLE BINDING

The binding of controls to data involves four distinct roles, each with a ing class These correspond to the work performed by the NET Framework onbehalf of bound controls, namely tracking which data has been bound to which con-trol, managing a bound data source, tracking specific bindings to a control, and man-aging the actual bindings A summary of these roles, along with the Windows Formsclass and property related to these roles, is outlined in the following table:

correspond-We will discuss these classes and properties in more detail as we build our example As

a brief explanation, the BindingContext class manages a collection of ManagerBase objects While any control can create an instance of this class in itsBindingContext property, the Form class creates one automatically to serve as the

Binding-4 Assign the tab order for the controls

within the Photo tab page as is shown

in the graphic.

Roles required for simple data binding

Tacking bound data BindingContext BindingContext property

Managing a bound data

source

BindingManagerBase Index into BindingContext collection:

BindingContext[ source ] BindingContext[ source, member ]

Managing bindings ControlBindingsCollection DataBindings property

Tracking a binding Binding Index into DataBindings collection:

DataBindings[ property ]

Ngày đăng: 07/07/2014, 04:20

TỪ KHÓA LIÊN QUAN