Address Book Case Study

Một phần của tài liệu Visual C 2012 How to Program _ www.bit.ly/taiho123 (Trang 924 - 930)

2. When the app executes, another compiler (known as the just-in-time compiler

22.9 Address Book Case Study

22.9 Address Book Case Study

Our final example (Fig. 22.32) implements a simpleAddressBookapp that enables users to perform the following tasks on the databaseAddressBook.mdf(which is included in the directory with this chapter’s examples):

• Insert new contacts

• Find contacts whose last names begin with the specified letters

• Update existing contacts

• Delete contacts

We populated the database with six fictional contacts.

Rather than displaying a database table in a DataGridView, this app presents the details of one contact at a time in severalTextBoxes. TheBindingNavigatorat the top of the window allows you to control whichrowof the table is displayed at any given time.

TheBindingNavigatoralso allows you toadda contact anddeletea contact—but only 21 // initialize data sources when the Form is loaded

22 private void Details_Load( object sender, EventArgs e )

23 {

24 // load Authors table ordered by LastName then FirstName 25

26 27 28 29

30 // specify DataSource for authorBindingSource 31

32 } // end method Details_Load 33 } // end class Details

34 } // end namespace MasterDetail

Fig. 22.32 | Manipulating an address book. (Part 1 of 2.)

Fig. 22.31 | Using aDataGridViewto display details based on a selection. (Part 2 of 2.)

dbcontext.Authors

.OrderBy( author => author.LastName ) .ThenBy( author => author.FirstName ) .Load();

authorBindingSource.DataSource = dbcontext.Authors.Local;

a) Use theBindingNavigator’s controls to navigate through the contacts in the database

when browsing thecompletecontact list. When you filter the contacts by last name, the app disables theAdd new( ) andDelete( ) buttons (we’ll explain why shortly). Clicking

Browse All Entriesenables these buttons again. Adding a row clears theTextBoxes and sets theTextBoxto the right ofAddress IDto zero to indicate that theTextBoxes now represent a new record. When you save a new entry, theAddress IDfield is automatically changed from zero to a unique ID number by the database. No changes are made to the underlying database unless you click theSave Data( ) button.

22.9.1 Creating theAddress BookApp’s GUI

We discuss the app’s code momentarily. First you’ll set up the entity data model and a WindowsForms app.

Step 1: Creating aClass LibraryProject for the Entity Data Model

Perform the steps in Section 22.5.1 to create aClass Libraryproject namedAddressExam- plethat contains an entity data model for theAddressBook.mdfdatabase, which contains only anAddressestable withAddressID,FirstName,LastName,EmailandPhoneNumber

columns. Name the entity data modelAddressModel.edmx. TheAddressBook.mdfdata- base is located in theDatabasesfolder with this chapter’s examples.

Fig. 22.32 | Manipulating an address book. (Part 2 of 2.)

b) Type a searchstringin the Last Name:TextBoxthen press Findto locate contacts whose last names begin with thatstring; only two names start with “Br” so theBindingNavigatorindicates two matching records

Displaying the first of two matching contacts for the current search

c) ClickBrowse All Entries to clear the searchstring and allow browsing of all contacts in the database

You can now browse through all six contacts

22.9 Address Book Case Study 885

Step 2: Creating aWindows Forms ApplicationProject forAddressBookApp Perform the steps in Section 22.5.2 to create a newWindows Forms Applicationproject named AddressBook in the AddressExample solution. Set theForm’s filename toCon-

tacts.cs, then set theForm’sTextproperty toAddress Book. Set theAddressBookproject as the solution’s startup project.

Step 3: Adding theAddressObject as a Data Source

Add the entity data model’sAddressobject as a data source, as you did with theAuthor object inStep 1of Section 22.5.3.

Step 4: Displaying the Details of Each Row

InDesignview, select theAddressnode in theData Sourceswindow. Click theAddress node’s down arrow and select theDetailsoption to indicate that the IDE should create a set ofLabel–TextBoxpairs to show the details of a single record at a time.

Step 5: Dragging theAddressData-Source Node to theForm

Drag theAddressnode from the Data Sourceswindow to theForm. This automatically creates aBindingNavigatorand theLabels andTextBoxes corresponding to the columns of the database table. The fields are placed in alphabetical order. Reorder the components, usingDesignview, so they’re in the order shown in Fig. 22.32. You’ll also want to change the tab order of the controls. To do so, selectVIEW > Tab Orderthen click theTextBoxes from top to bottom in the order they appear in Fig. 22.32.

Step 5: Making theAddressID TextBox ReadOnly

TheAddressIDcolumn of theAddressestable is anautoincremented identity column, so users shouldnotbe allowed to edit the values in this column. Select theTextBoxfor the

AddressIDand set itsReadOnlyproperty toTrueusing thePropertieswindow.

Step 6: Adding Controls to Allow Users to Specify a Last Name to Locate

While theBindingNavigatorallows you to browse the address book, it would be more convenient to be able to find a specific entry by last name. To add this functionality to the app, we must create controls to allow the user to enter a last name and provide event han- dlers to perform the search.

Add aLabelnamedfindLabel, aTextBoxnamedfindTextBox, and aButtonnamed

findButton. Place these controls in aGroupBoxnamedfindGroupBox, then set itsText property toFind an entry by last name. Set theTextproperty of theLabeltoLast Name:

and set theTextproperty of theButtontoFind.

Step 7: Allowing the User to Return to Browsing All Rows of the Database

To allow users to return to browsing all the contacts after searching for contacts with a spe- cific last name, add aButtonnamedbrowseAllButtonbelow thefindGroupBox. Set the

Textproperty ofbrowseAllButtontoBrowse All Entries. 22.9.2 Coding theAddress BookApp

TheContacts.cscode-behind file is split into several figures (Figs. 22.33–22.37) for pre- sentation purposes.

MethodRefreshContacts

As we showed in previous examples, we must connect theaddressBindingSourcethat controls the GUI with theDbContextthat interacts with the database. In this example, we declare theAddressEntities DbContextobject at line 20 of Fig. 22.33, but create it and initiate the data binding in theRefreshContactsmethod (lines 23–43), which is called from several other methods in the app. When this method is called, ifdbcontextis not

null, we call itsDisposemethod, then create anew AddressEntities DbContextat line 30. We do this so we can re-sort the data in the entity data model. If we maintained one

dbcontext.Addressesobject in memory for the duration of the program and the user changed a person’s last name or first name, the records would still remain in their original order in thedbcontext.Addressesobject, even if that order is incorrect. Lines 34–37 or- der theAddressobjects byLastName, thenFirstNameand load the objects into memory.

Then line 40 sets theaddressBindingSource’sDataSourceproperty todbcontext.Ad- dresses.Localto bind the data in memory to the GUI.

1 // Fig. 22.33: Contact.cs

2 // Manipulating an address book.

3 using System;

4 using System.Data;

5 using System.Data.Entity;

6 using System.Data.Entity.Validation;

7 using System.Linq;

8 using System.Windows.Forms;

9

10 namespace AddressBook 11 {

12 public partial class Contacts : Form

13 {

14 public Contacts()

15 {

16 InitializeComponent();

17 } // end constructor 18

19 // Entity Framework DbContext 20

21

22 // fill our addressBindingSource with all rows, ordered by name 23 private void RefreshContacts()

24 {

25 // Dispose old DbContext, if any 26

27 28

29 // create new DbContext so we can reorder records based on edits 30

31

32 // use LINQ to order the Addresses table contents 33 // by last name, then first name

Fig. 22.33 | Creating theBooksDataContextand defining methodRefreshContactsfor use in other methods. (Part 1 of 2.)

private AddressExample.AddressBookEntities dbcontext = null;

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

dbcontext = new AddressExample.AddressBookEntities();

22.9 Address Book Case Study 887

MethodContacts_Load

MethodContacts_Load(Fig. 22.34) callsRefreshContacts(line 48) so that the first re- cord is displayed when the app starts. As before, you create theLoadevent handler by dou- ble clicking theForm’s title bar.

MethodaddressBindingNavigatorSaveItem_Click

MethodaddressBindingNavigatorSaveItem_Click(Fig. 22.35) saves the changes to the database when theBindingNavigator’sSave DataButtonis clicked. (Remember to enable this button.) The AddressBook database requires values for the first name, last name, phone number and e-mail. If a field is empty when you attempt to save, aDbEntityVal- idationExceptionexception occurs. We callRefreshContactsafter saving to re-sort the data and move back to the first element.

34 35 36 37 38

39 // specify DataSource for addressBindingSource 40

41 addressBindingSource.MoveFirst(); // go to first result 42 findTextBox.Clear(); // clear the Find TextBox

43 } // end method RefreshContacts 44

45 // when the form loads, fill it with data from the database 46 private void Contacts_Load( object sender, EventArgs e )

47 {

48

49 } // end method Contacts_Load 50

Fig. 22.34 | CallingRefreshContactsto fill theTextBoxes when the app loads.

51 // Click event handler for the Save Button in the 52 // BindingNavigator saves the changes made to the data 53 private void addressBindingNavigatorSaveItem_Click(

54 object sender, EventArgs e )

55 {

56 Validate(); // validate input fields

57 addressBindingSource.EndEdit(); // complete current edit, if any 58

59 // try to save changes

60 try

61 {

Fig. 22.35 | Saving changes to the database when the user clicksSave Data. (Part 1 of 2.) Fig. 22.33 | Creating theBooksDataContextand defining methodRefreshContactsfor use in other methods. (Part 2 of 2.)

dbcontext.Addresses

.OrderBy( entry => entry.LastName ) .ThenBy( entry => entry.FirstName ) .Load();

addressBindingSource.DataSource = dbcontext.Addresses.Local;

RefreshContacts(); // fill binding with data from database

MethodfindButton_Click

MethodfindButton_Click(Fig. 22.36) uses LINQ query syntax (lines 79–83) to select only people whose last names start with the characters in thefindTextBox. The query sorts the results by last name then first name. In LINQ to Entities, youcannotbind a LINQ que- ry’s results directly to aBindingSource’sDataSource. So, line 86 calls the query object’s

ToListmethod to get aListrepresentation of the filtered data and assigns theListto the

BindingSource’sDataSource. When you convert the query result to aList, only changes toexistingrecords in theDbContextare tracked by theDbContext—any records that you add or remove while viewing the filtered data would be lost. For this reason we disabled the

Add newandDeletebuttons when the data is filtered. When you enter a last name and click

Find, theBindingNavigatorallows the user to browse only the rows containing the match- ing last names. This is because the data source bound to theForm’s controls (the result of the LINQ query) has changed and now contains only a limited number of rows.

62 dbcontext.SaveChanges(); // write changes to database file

63 } // end try

64 catch ( DbEntityValidationException )

65 {

66 MessageBox.Show( "Columns cannot be empty",

67 "Entity Validation Exception" );

68 } // end catch

69 70

71 } // end method addressBindingNavigatorSaveItem_Click 72

73 // use LINQ to create a data source that contains only people 74 // with last names that start with the specified text

75 private void findButton_Click( object sender, EventArgs e )

76 {

77 // use LINQ to filter contacts with last names that 78 // start with findTextBox contents

79 80 81 82 83 84

85 // display matching contacts 86

87 addressBindingSource.MoveFirst(); // go to first result 88

89 // don't allow add/delete when contacts are filtered 90 bindingNavigatorAddNewItem.Enabled = false;

91 bindingNavigatorDeleteItem.Enabled = false;

92 } // end method findButton_Click 93

Fig. 22.36 | Finding the contacts whose last names begin with a specifiedString. Fig. 22.35 | Saving changes to the database when the user clicksSave Data. (Part 2 of 2.)

RefreshContacts(); // change back to initial unfiltered data

var lastNameQuery =

from address in dbcontext.Addresses

where address.LastName.StartsWith( findTextBox.Text ) orderby address.LastName, address.FirstName

select address;

addressBindingSource.DataSource = lastNameQuery.ToList();

Một phần của tài liệu Visual C 2012 How to Program _ www.bit.ly/taiho123 (Trang 924 - 930)

Tải bản đầy đủ (PDF)

(1.020 trang)