Tutorial: MSSQL- Windows Form Development
Multi-User Application With Custom Record Lockout #3
[Login, RecoordLock DB, Authentication, Configure Dynamic Data Combo, Password Fields, CheckBoxes, & Tab Control]

Dr. Thomas E. Hicks
Computer Science Department
Trinity University


Purpose

The purpose of this series of tutorials is to show how to configure a Windows Application Form, using Visual Studio, to process a multi-form, multi-user network application. This tutorial will briefly review many of the concepts demonstrated in some of the other tutorials.

Prerequisite Condition: each of our major database tables must have a unique, auto-incremented, integer field called ID.

This portion of the tutorial will examine and configure a combobox filled by a database table, checkbox controls, password textboxes, and tabcontrol configuration.


About Part 1 Of Tutorial

This tutorial is fourth in a series of Windows Form Development Multi-User Application With Custom Record Lockout #1 [Database Configuration, Database Authentication, Generic Database Utilities, Etc.]. The topics in part 1 are as follows:


About Part 2 Of Tutorial

This tutorial is fourth in a series of Windows Form Development Multi-User Application With Custom Record Lockout #2 [Query Set Views & Navigation Buttons & Filters & Order By]. The topics in part 2 are as follows:


Sections In This Tutorial Part 3

Part III-A:  Use ComboBoxes To Reduce Data Entry Errors [Database Enables Dynamic ComboBoxes]

Part III-B:  Use CheckBoxes To Reduce Data Entry Errors

Part III-C:  Hide The Password Data

Part III-D:  Configuring Tab Control For The User Form

Part III-E:  LibraryApp Authentication

Part III-F:  Login Processing

Part III-G:  Carriage Return/Enter Form Processing

Part III-H:  Final Testing

Part III-I:  Temporary Main.cs Change For Rapid Development

Part III-J:  For You To Do


 If You Have Difficulty With This Tutorial,  You Might Find These Help Prepare You For This Tutorial
I Recommend That My Students Complete The Tutorials In This Order!

 

Tutorial: MSSQL TU Database-Construction Using Microsoft SQL Server

Tutorial: MSSQL-Forms - Windows Application & Basic Form Properties

Tutorial: MSSQL-Forms - Windows Application - Labels & Textboxes

Tutorial: MSSQL-Forms - Windows Application - Buttons

Tutorial: MSSQL-Connection\MSSQL-Connections

Tutorial: MSSQL-Forms - Windows Application - Menu - Multiple Forms

Tutorial: MSSQL-Visual Studio MenuStrip Application With Multiple Windows

MSSQL-Forms - Windows Application - Web Browser

MSSQL-Windows-Forms-ComboBox.html


Copy Project

1] Copy folder Library-Net-Multi-User-2 to folder Library-Net-Multi-User-3. I always recommend making a backup copy about ever hour or so.


Part III-A:
Use ComboBoxes To Reduce Data Entry Errors
[Database Enables Dynamic ComboBoxes]

1] It goes without saying that a combobox would be better for the MajorID selection. Why should the user have to look up the number that is appropriate for the respective major? Why not avoid the problem that occurs when a user enters the MajorID incorrectly?

2] We could enter all of the major choices directly into the combobox; this means that the code would have to be altered if the selection of majors either increases or decreases. Using the database to fill the combobox is a much more professional choice; changes can be made to the database and your form will always be updated each time the Users form is created.

 

Add The ComboBox Control

1] Using the mouse, drag a ComboBox control from the Toolbox menu to your Users form. (See Below!)

 

Create a Database Connection To LibraryApp For The ComboBox Control

1] Using the mouse, expand the ComboBox control. (See Below!)

2] Check the Use data bound items. (See Below!)

3] Hold down the Data Source drop-down control. (See Below!)

4] Select Add Project Data Source. (See Below!)

5] Using the mouse, select the Next button. (See Below!)

6] Using the mouse, select the New Connection.. button. (See Below!)

7] Select Microsoft SQL Server. Using the mouse, select the Continue button. (See Below!)

8] Enter the name SQL Server Data Source (NET1\SQLEXPRESS for me). Enter, or select, LibraryApp. Using the mouse, select the Test Connection button. (See Below!)

9] Using the mouse, select the OK button. (See Below!)

10] Using the mouse, select the OK button. (See Below!)


 

11] Using the mouse, select the Next button. (See Below!)

 

12] We can use this same LibraryApp database connection for other controls; save it. Using the mouse, select the Next button. (See Below!)

 

Configure The ComboBox Control


1] Select both the ID and Major from the Majors table. Using the mouse, select the Finish button. (See Below!)

2]  Using the mouse, select the Display Member drop-down control. (See Below!)

3] Select Major as the Display Member. (See Below!)

 

4] Using the mouse, select the Value Member drop-down control. (See Below!)

5] Select Major as the Display Member. (See Below!)

 
 
 

Name The ComboBox Control & Make It Consistent, In Appearance With The Rest Of The Form

 
1] Change the Property Name of the new ComboBox to cbMajorID.  (See Below!)

 

2] Change the Property Font of the new ComboBox to Arial, 12 Point, Bold.  (See Below!)

 

Modify FillFormVariables To Update The ComboBox Control


1] Add an entry in FillFormVariables to automatically control the cbMajorID from the current database query record.  (See Below!)

 

2] Execute the program. Note that when you go to Tom Hicks, the Computer Science Major now loads properly.  (See Below!)


3]  Note that when you go to Steven, the Math Major now loads properly.  (See Below!)

3]  Delete txtMajorID from the Users form and slide cbMajorID up in it's place. Aldo delete the line of code associated with filling txtMajorID.  (See Below!)

5]  Execute the form again. Note the choices that can be selected with ComboBox cbMajorID.  (See Below!)

 

New Controls On The Graphical Representation Of The Users Form


1]  Note that the LibraryAppDataSet, the majorsBindingSource, and the majorsTableAdapter that were created (and added to our Users form) as we walked through the steps above.  (See Below)


 

 

When To Use The ComboBox Control

1]  ComboBox controls should be used to reduce data entry problems whenever possible; if we can feed the choices with a database, all the better. If we were to have a text field for Major, then users might enter cs, CS, Computer Science, Comp Sci, computer science, comp sci, etc. for the field; in addition to abbreviations, and case differentially, some of the users will spell things incorrectly. This lack of consistency would make searching and order by difficult and inadequate at best.

2] In this same train of thought, something needs to be done to field txtAdministrator; among the things users might enter would be Y, y, N, n, T, t, F, f, True, true, False, false, yes, Yes, no, No, YES, NO, etc. We could use a Yes or No radio button. We could use a Yes or No ComboBox control. Since we have already demonstrated a combobox control, I shall use a checkbox control to replace txtAdministrator.
 


Part III-B:
Use CheckBoxes To Reduce Data Entry Errors

1]  In an effort to reduce data entry problems, we shall use a checkbox control to replace txtAdministrator.

 

Add The ComboBox Control

1] Using the mouse, drag a CheckBox control from the Toolbox menu to your Users form. (See Below!)

 
 

Name The CheckBox Control & Make It Consistent, In Appearance With The Rest Of The Form

 
1] Change the Property Name of the new ComboBox to ckAdministrator.  (See Below!)
 
 
2] Change the Property Text blank/nothing.  (See Below!)

 

Modify FillFormVariables To Update The ComboBox Control

1] Change FillFormVariables to place a check mark for administrators.  (See Below!)

2] Execute the program. Note that Tom Hicks is an administrator. Administrator = T and the box is checked.  (See Below!)

3] Also note that Noreen Gilbert is not an administrator. Administrator = F and the box is not checked.  (See Below!)

4] Examine the database and confirm that the checkbox is working properly for all users.  (See Below!)

5] Change FillFormVariables; remove the assignment for txtAdministrator.  (See Below!)

6] Remove txtAdministrator from the form and shift cbAdministrator into it's place.  (See Below!)

 


Part III-C:
Hide The Password Data

1]  We now know that the password data is properly loaded into our form; it is time to secure the contents.
 


Modify txtPassword Field

1]  Select the Properties of the field txtPassword; change the PasswordChar to *. (See Below!).

2]  You can see that the Password is a bit more secure, but knowing that it is four characters often reduces the security potential; I personally tend to blank pad the password, programmatically, to 20 characters to increase security. When comparing the password, for login purposes, it is quite simple to strip those trailing blanks. (See Below!).

 


Part III-D:
Configuring Tab Control For The User Form

1]  It is tab order that is used to determine which control gets focus. Focus may be transferred to and from input fields, buttons, radio buttons, tabs, checkboxes, and comboboxes;  we call  this tab order because you can change focus from control to control using the tab key on the Windows form.

2] Some type of tab order is an important aspect in form usability.

3] By default, Tab order for individual controls is usually set to true, thus making the control usable.

4] Tab order can be set with the properties control or through program code.

5] The initial tab order is determined by the order in which the controls are created on the form.
 


The Existing Tab Order For Form Users.cs

1] Your tab order may well differ from mine. When I run the application and place the cursor in field txtFirst and hit the tab key,

2] I am transferred to field txtLast; when hit the tab key,

3] I am transferred to field txtUserName; when hit the tab key,

4] I am transferred to field txtInitial; when hit the tab key,

5] I am transferred to field txtPassword; when hit the tab key,

6] I am transferred to button btnTesting; when hit the tab key,

7] I am transferred to field txtMajorID etc.

 


The Existing Tab Order

1] A form might include a Delete button. Suppose the tab control arrives on the delete button; this would make it easy for the user to hit the enter key and accidently delete a record. By and large I do not want buttons included it the Tab Control.

2] Ideal Tab Control ==> I would like my ideal tab control to process from First to Initial to Last to UserName to Password to Gender to Administrator and then back to First.

3] Using the mouse, hold down the View Menu and select Tab Order. (See Below!)

4] The yellow lines below help to graphically illustrate the current Tab Order.

 


Remove All Buttons, ComboBoxes, & Fields From The Tab Order

1] Select the btnA. Change the TabStop Property to False so that the button is not included in the Tab Control sequence. (See Below!)

 2] Do likewise for each and every button. Set  the TabStop Property to False for all buttons.

3] Do likewise for comboboxes cbOrderBy and cbSelect. Set  the TabStop Property to False for these two comboboxes.

4] Do likewise for lbTrace. Set the TabStop Property to False for lbTrace.

 


Set The Tab Order For Those Items To Be Included In The Tab Sequence

1] Note that those items, that had the TabStop Property set to False , still appear (and are numbered), in the tab control list below.

2] Each item on the form has a potential tab control associated with it; some of these items, such as the labels,  may not be tabbed.

3] The TabControl will have a number assigned to it; My current number is 95, but yours might be different. Using the mouse, touch the TabControl number one time. (See Below!)

3] The TabControl will now have the number 0 assigned to it.  (See Below!)

4] Using the mouse, touch the number associated with txtFirst (mine is 0.3.0).  (See Below!)

5] The value did not change, but yours may have changed. TxtFirst is now the first field in our ideal tab solution. The number associated with txtFirst is 0.3.0.  (See Below!)

6] Using the mouse, touch the number associated with txtInitial (mine is 0.3.1).  (See Below!)

7] The value did not change, but yours may have changed. TxtFirst is now the second field in our ideal tab solution. The number associated with TxtFirst is 0.3.1.  (See Below!)

8] Using the mouse, touch the number associated with txtLast (mine is 0.3.3).  (See Below!)

9] The value did change, but yours may not have changed. TxtLast is now the third field in our ideal tab solution. The number associated with TxtLast is 0.3.2.  (See Below!)

10] Using the mouse, touch the number associated with txtUserName (mine is 0.3.7).  (See Below!)

11] The value did change, but yours may not have changed. txtUserName is now the fourth field in our ideal tab solution. The number associated with txtUserName is 0.3.3.  (See Below!)

12] Using the mouse, touch the number associated with txtPassword (mine is 0.3.11).  (See Below!)

13] The value did change, but yours may not have changed. txtPassword is now the fifth field in our ideal tab solution. The number associated with txtPassword is 0.3.4.  (See Below!)

14] Using the mouse, touch the number associated with cbGenderID (mine is 0.3.17).  (See Below!)

15] The value did change, but yours may not have changed. cbGenderID is now the sixth field in our ideal tab solution. The number associated with cbGenderID is 0.3.5.  (See Below!)

16] Using the mouse, touch the number associated with ckAdministrator (mine is 0.3.18).  (See Below!)

17] The value did change, but yours may not have changed. ckAdministrator is now the sixth field in our ideal tab solution. The number associated with ckAdministrator is 0.3.6.  (See Below!)

17] It is time to store/save this configuration.  Using the mouse, hold down the View Menu and select Tab Order. Save the form.  (See Below!)

 


The Ideal Tab Order For Form Users.cs

1] As you prepare to execute the form for final testing, note that all tab controls colored with turquoise (in the image below) have the TabStop Property to False.

2] As you prepare to execute the form for final testing, note that all tab controls colored with lime green (in the image below) are not important.

3] As you prepare to execute the form for final testing, note that all tab controls colored with blue (in the image below) have the tab stops configured with respect to our ideal tabl sequence. Test it! Make changes if necessary!

 


Part III -E:
Create Database RecordLock

1]  We are going to use SQL Server accounts for all login.

2] We are going to create a second database, called  RecordLock, to store record locks for all tables and all databases.

3] The directions below will help you create database RecordLock.

 


Add New User RecordLockAdmin

1]Using Microsoft SQL Management Studio Express, create a database called RecordLock.

2] Add a table, called Locks, to database RecordLock.

3] Add the fields below to table Locks!

4] Add a table, called Users, to database RecordLock.

5] Add the fields below to table Users! Note that UserID is an auto-incrementing primary integer key.

 


Add New User RecordLockAdmin

1] Add a user, called RecordLockAdmin, whose default database shall be RecordLock. (See Below!)

2] User Map RecordLockAdmin to the RecordLock database. (See Below!)

3] Enable User RecordLockAdmin to Connect, Authenticate, Update, Insert, Delete, and Select. (See Below!)

4] We shall use user RecordLockAdmin to read, write, and update locks on our database. This is much simpler, and more secure,  than granting such privileges to each and every user. (See Below!)


Part III-E:
LibraryApp Authentication

1] We are about to work on our Login.cs form.  A SQL Server database will have a collection of valid users. You should have set up student in Part II of this tutorial set. You can see a screen capture of the Permissions tab when looking at the properties of my LibraryApp below.

2] I have three users (meggen, student, and  thicks) that have Authenticate and Connect privileges on my database. (See Below!)

3] Only meggen, student, and  thicks shall be able to login with our login form.

4] Each user will have only those privileges asserted in the database; if meggen has update permission, he will be able to update a user record or a book record. If thicks has insert permission, he will be able to add a new book or user.

5] When one user needs access to a record immediately, it is great to know who has the record locked and how to get in touch with that person. Each SQL User who shall be able to use a multi-user application shall have an entry in the Users table of database RecordLock.

6] For each SQL User who has access to LibraryApp

add a  corresponding record to RecordLock => Users which might provide

6] The RecordLock database may well have users, such as sa, who do not have access to the LibraryApp database; that is ok. The RecordLock dat

6] We will discuss locking records much more in depth in Part IV of this tutorial set, but a couple of comments are in order.

7] When one user chooses to edit a record, they shall be granted a lock on that record for some fixed period of time; other uses requesting that record shall be placed in a queue and granted access accordingly.

8] There will be times when a user absolutely needs control at a record immediately. When a user requests a locked record, we are going to tell that user the name, phone, and office information of the person who currently has the record locked; this might well provide a way to call, or visit,  the person who has the record locked and ask them to release it.

9] For testing purposes, make sure that you have at least two users with access to your LibraryApp Database; I encourage you to add three or four users.

 


Part III-F:
Login Processing

1] The SQL User system shall authenticate our users. In order for a user to log in, he/she must have a valid SQL username and password.

2] After the user is authenticated with the LibraryApp, the UserID, for that user, will be read from the RecordLock database. We shall use that UserID in Part IV.
 


Update Form MainMenu.cs

1] Add LoggedIn and LoginUserID to form MainMenu.cs.

 
Update Form Login.cs

1] Using the mouse, double click on btnLogin to create the btnLogin_Click event.. (See Below!)

2] Add the following code to function btnLogin_Click on the Login.cs form.  (See Below!)

3] Note that there are two Message.Box.Show (Green in color) that are commented out in the code above. The first one should reveal the number of the users in the LibraryApp Users table. The second should reveal the UserID, from the RecordLock Users table, of the person who is logging into the system. Uncomment both of these!

4] Execute the LibraryApp system. Launch the Login form. Test the form with both valid and invalid data. Once it is working properly, re-comment out the same two MessageBox.Show lines of code.


Update Form  MainMenu.cs

1] We would ultimately like our application to start by automatically bringing up the Login Form so that a user can log in. Change your MainMenu_Load to be as follows.

2] It is only after a user has successfully logged in that we would like the user to be able to bring up the Users form. Change your MainMenu_Load to be as follows.

3] It is only after a user has successfully logged in that we would like the user to be able to bring up the Books form. Change your MainMenu_Load to be as follows.

4] Execute the LibraryApp system. Test it! Only logged in users should be able to access forms Books and Users.


Part III-G:
Carriage Return/Enter Form Processing

1] Execute the LibraryApp system. Note that in order to get from txtUserName to txtPassword, you have to either hit the tab key or use the mouse to change fields. Most users would also like to be able to advance by hitting the Enter (Carriage Return) Key.

2] Use the process described above to set the tab order for the Login form to match that below!


Changing Enter To Tab One TextBox At A Time

1] Many uses solve this by creating an KeyPressed event for each and every textbox on a form and inserting code similar to that below. I encourage you to try this. It does work, but it is time consuming when a form has dozens of textboxes.

2] Using the mouse, touch field txtUserName on form Login.cs. Go to the Properties Panel. Touch the Event Manager at the top of the Properties Panel. Using the mouse, double-click on the KeyDown event property. (See Below!)   Do the same for txtPassword. This will create a keydown event for both txtUserName and txtPassword.

3] When you add the code below, pressing the enter key in either of these two boxes will have the same effect as pressing the tab key.

4] Execute the LibraryApp system. Enter UserName =  student (note I have colored the cursor red). Hit the Enter Key.

5] Note that he cursor (red) has moved to the next tab field (which is txtPassword).

6] Enter Password =  student (note I have colored the cursor red). Hit the Enter Key.

7] Note that the focus has moved to the next tab field (which is the btnLogin).


 


Changing Enter To Tab For The Entire Form

1] I personally prefer a solution that does not require changes to each and every textbox.

2]  Using the mouse, touch form Login.cs (not on one of the controls). Go to the Properties Panel. Touch the general Properties Manager at the top of the Properties Panel. Using the mouse, change the KeyPreview property to True. (See Below!)  

3] Using the mouse, touch form Login.cs (not on one of the controls). Go to the Properties Panel. Touch the Event Manager at the top of the Properties Panel. Using the mouse, double-click on the KeyPress event property. (See Below!)   This will create a keypressed event for entire form.

4] Remove the code you previously placed in txtUserName_KeyDown and txtPassword_KeyDown.

5] Change the Login_KeyPress code to be as follows:

6] Execute the LibraryApp system. Enter UserName =  student (note I have colored the cursor red). Hit the Enter Key.

7] Note that he cursor (red) has moved to the next tab field (which is txtPassword).

8] Enter Password =  student (note I have colored the cursor red). Hit the Enter Key.

9] Note that the focus has moved to the next tab field (which is the btnLogin).

10] Our system is now much more professional and user friendly.
 


Part III-H:
Final Testing

1] You should have at least two SQL Login Users. I plan to test the system with two users --> thicks and student. Note that student and thicks are both  SQL Login Users. You should have student and at least one other; add them now if necessary!

2]  Note that student and thicks are users in the LibraryApp. These users must have Authenticate, Connect, Delete, Insert, and Update privileges granted. Your LibraryApp database should include student and at least one other user with these privileges granted; add them now if necessary!

3]  Open form Users.cs. Write the code for function TestModule24. (See Below!)

4 Make the following changes (in red) in function TestingMaster on form Users.cs.

        //================================================================================//
        //                                  TestingMaster                                 //
        //================================================================================//
        //  Purpose: Testing Master which evokes TestModule1, TestModule2, ...            //
        //                                                                                //
        //  Written By : Dr. Thomas E. Hicks                    Environment : .NET 2005/8 //
        //        Date : xx/xx/xxxx                                Language : C#          //
        //================================================================================//
        public void TestingMaster()
        {
            int UserClassDiagnosticLevel = 24;

            if (UserClassDiagnosticLevel == 0)
                TestAll();
            if (UserClassDiagnosticLevel == 1)
                TestModule1();
            if (UserClassDiagnosticLevel == 2)
                TestModule2();
            if (UserClassDiagnosticLevel == 3)
                TestModule3();
            if (UserClassDiagnosticLevel == 4)
                TestModule4();
            if (UserClassDiagnosticLevel == 5)
                TestModule5();
            if (UserClassDiagnosticLevel == 6)
                TestModule6();
            if (UserClassDiagnosticLevel == 7)
                TestModule7();
            if (UserClassDiagnosticLevel == 8)
                TestModule8();
            if (UserClassDiagnosticLevel == 9)
                TestModule9();
            if (UserClassDiagnosticLevel == 10)
                TestModule10();
            if (UserClassDiagnosticLevel == 11)
                TestModule11();
            if (UserClassDiagnosticLevel == 12)
                TestModule12();
            if (UserClassDiagnosticLevel == 13)
                TestModule13();
            if (UserClassDiagnosticLevel == 14)
                TestModule14();
            if (UserClassDiagnosticLevel == 15)
                TestModule15();
            if (UserClassDiagnosticLevel == 16)
                TestModule16();
            if (UserClassDiagnosticLevel == 17)
                TestModule17();
            if (UserClassDiagnosticLevel == 18)
                TestModule18();
            if (UserClassDiagnosticLevel == 19)
                TestModule19();
            if (UserClassDiagnosticLevel == 20)
                TestModule20();
            if (UserClassDiagnosticLevel == 21)
                TestModule21();
            if (UserClassDiagnosticLevel == 22)
                TestModule22();
            if (UserClassDiagnosticLevel == 23)
                TestModule23();
            if (UserClassDiagnosticLevel == 24)
                TestModule24();
        }

5]  Make the following changes (in red) in function TestinAll on form Users.cs.

        //================================================================================//
        //                                  TestingAll                                    //
        //================================================================================//
        //  Purpose: Test all of the functions: TestModule11, TestModule12, ...           //
        //                                                                                //
        //  Written By : Dr. Thomas E. Hicks                    Environment : .NET 2005/8 //
        //        Date : xx/xx/xxxx                                Language : C#          //
        //================================================================================//
        public void TestAll()
        {

            TestModule11();
            TestModule12();
            TestModule13();
            TestModule14();
            TestModule15();
            TestModule16();
            TestModule17();
            TestModule18();
            TestModule19();
            TestModule20();
            TestModule21();
            TestModule22();
            TestModule23();
            TestModule24();
        }

6]  Execute the LibraryApp system. Enter UserName =  student   (Hit the Enter Key).  Enter Password =  student   (Hit the Enter Key or Push btnLogin). (See Below!)

7]  Launch the Users form (using the mouse, hold down the Users Menu and select ViewUsers).  Push btnTesting. (See Below!)

8]  Variable LoggedIn, on the MainMenu form, has been successfully set to true.  As you look at a snapshot of the Users table of database RecordLock (below), you can see that strLoginUserID, on the MainMenu form, has been correctly set to 4.

9]  Check the other user. Re-Launch the Login form. Enter UserName =  ???? [thicks for me]   (Hit the Enter Key).  Enter Password =  ????   (Hit the Enter Key or Push btnLogin). (See Below!)

7]  Once again push btnTesting on form Users. Variable LoggedIn, on the MainMenu form, is still set to true.  As you look at a snapshot of the Users table of database RecordLock (above), you can see that strLoginUserID, on the MainMenu form, has been correctly set to 2.

 


Part III-I:
Temporary Main.cs Change For Rapid Development

1] Our Login form is completed.

2] We have many more changes to make in the Users.cs form as we continue to develop and implement the record lock-out functionality in the following tutorials.

3] During this development and testing phase, we do not want to bother logging in each time we wish to test new functions.

4] Change MainMenu_Load to the following. Assign your StrLoginUserID to be that number that corresponds with your student UserID (as assigned in the RecrodLock Users database table) of your system.

5]  Execute the LibraryApp system.  Push btnTesting. (See Below!)

6] Things will now proceed logically as if student had logged in. The Users table is automatically launched for testing.

7] You can make the necessary changes to reverse this testing process when the project is completed.

8] Of course you can skip these changes and login each time if you prefer?


Part III-J:
For You To Do

1] This is your opportunity to put into practice what you have learned. Do the Following!


Modify Books.cs

1] Configure a combobox, called cbGenreID to be dynamically filled by the Database Table Genre.

2] Configure the ideal TabOrder to proceed from Title to Author to Price to Genre and back to Title. Those items that are turquoise should have TabStop = false. Those items that are Navy should have TabStop = true. Those items that are lime green are not important.

3] Configure the Enter Key to process the TabOrder.


Modify Users.cs

1] Configure the Enter Key to process the TabOrder.