Creating the Territory User Interface


You are ready to create the user interface for your Territory object. First, add a new, inherited form to the NorthwindTraders project and call it frmTerritoryList.vb. When the Inheritance Picker form displays, select the frmListBase form.

Caution

Visual inheritance has a requirement at design-time. Often one form will inherit from another, but when you try to view the inherited form you get an error saying that the form cannot be loaded in the designer. There are a number of different error messages you can get when this occurs, but what it comes down to is that there is a problem in the base form. This is usually caused by some requirement of the constructor that has not been met. The inherited form must be able to compile at design-time! One way of making sure this requirement is met is to always have the default constructor in the base form and just overload it.

Creating the frmTerritoryList Form

Before you do anything else, you need to alter the constructor on the frmTerritoryList class so that the call to MyBase.New includes the title of the Territory List. It should look like the following:

 MyBase.New(Territories) 

This form is fairly similar to the frmRegionList form. There are no major differences between the two forms (except for the properties), so go ahead and add the code in Listing 7-11 to your list form (note that I have not included the Windows Forms Designer-generated code).

Listing 7-11: The frmTerritoryList Code Module and Class

start example
 Option Explicit On Option Strict On Imports NorthwindTraders.NorthwindUC Public Class frmTerritoryList     Inherits.UserInterface..frmListBase     Private mobjTerritoryMgr As TerritoryMgr     Private WithEvents mfrmEdit As frmTerritoryEdit     Private WithEvents mobjTerritory As Territory     Public Sub New()         MyBase.New("Territories")         'This call is required by the Windows Form Designer.         InitializeComponent()         'Add any initialization after the InitializeComponent() call         LoadList()     End Sub #Region " Windows Form Designer generated code " 'Form overrides dispose to clean up the component list.     Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)         If disposing Then             If Not (components Is Nothing) Then                 components.Dispose()             End If         End If         MyBase.Dispose(disposing)     End Sub     'Required by the Windows Form Designer     Private components As System.ComponentModel.IContainer     'NOTE: The following procedure is required by the Windows Form Designer     'It can be modified using the Windows Form Designer.     'Do not modify it using the code editor.     <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()         components = New System.ComponentModel.Container     End Sub #End Region  Private Sub LoadList()         Dim objTerritory As Territory         Dim objDictEnt As DictionaryEntry         Try             lvwList.BeginUpdate()             If lvwList.Columns.Count = 0 Then                 With lvwList                     .Columns.Add("Territory ID", CInt(.Size.Width / 1) - 8, _                     HorizontalAlignment.Left)                     .Columns.Add("Territory Description", CInt(.Size.Width _                     / 1) - 8, HorizontalAlignment.Left)                     .Columns.Add("Region", CInt(.Size.Width / 1) - 8, _                     HorizontalAlignment.Left)                 End With             End If              lvwList.Items.Clear()              mobjTerritoryMgr = New TerritoryMgr()              For Each objDictEnt In mobjTerritoryMgr                  objTerritory = CType(objDictEnt.Value, Territory)                  Dim lst As New ListViewItem(objTerritory.TerritoryID)                  lst.SubItems.Add(objTerritory.TerritoryDescription)                  lst.SubItems.Add(objTerritory.Region.RegionDescription)                  lvwList.Items.Add(lst)              Next             lvwList.EndUpdate()             lblRecordCount.Text = "Record Count: " & lvwList.Items.Count         Catch exc As Exception             LogException(exc)         End Try     End Sub     Protected Overrides Sub AddButton_Click(ByVal sender As Object, _     ByVal e As System.EventArgs)         Try             If mfrmEdit Is Nothing Then                 mobjTerritory = New Territory()                 mfrmEdit = New frmTerritoryEdit(mobjTerritory)                 mfrmEdit.MdiParent = Me.MdiParent                 mfrmEdit.Show()             End If         Catch exc As Exception             LogException(exc)         End Try     End Sub     Private Sub mfrmEdit_Closed(ByVal sender As Object, _     ByVal e As System.EventArgs) Handles mfrmEdit.Closed         mfrmEdit = Nothing     End Sub     Private Sub mobjTerritory_ObjectChanged(ByVal sender As Object, _     ByVal e As ChangedEventArgs) _     Handles mobjTerritory.ObjectChanged         Try             Dim lst As ListViewItem             Dim objTerritory As Territory = CType(sender, Territory)             Select Case e.Change                 Case ChangedEventArgs.eChange.Added                     mobjTerritoryMgr.Add(objTerritory)                     lst = New ListViewItem(objTerritory.TerritoryID)                     lst.SubItems.Add(objTerritory.TerritoryDescription)                     lst.SubItems.Add(objTerritory.Region.RegionDescription)                     lvwList.Items.Add(lst)                     lblRecordCount.Text = "Record Count: " _                     & lvwList.Items.Count                 Case ChangedEventArgs.eChange.Updated                     For Each lst In lvwList.Items                         If lst.Text = objTerritory.TerritoryID Then                             lst.SubItems(1).Text = _                             objTerritory.TerritoryDescription                             lst.SubItems(2).Text = _                             objTerritory.Region.RegionDescription                             Exit For                         End If                     Next             End Select             lvwList.Sort()         Catch exc As Exception             LogException(exc)         End Try     End Sub     Protected Overrides Sub EditButton_Click(ByVal sender As Object, _     ByVal e As System.EventArgs)         Try             If mfrmEdit Is Nothing Then                 If lvwList.SelectedItems.Count > 0 Then                     mobjTerritory = _                     mobjTerritoryMgr.Item(lvwList.SelectedItems(0).Text)                     mobjTerritory.LoadRecord()                     mfrmEdit = New frmTerritoryEdit(mobjTerritory)                     mfrmEdit.MdiParent = Me.MdiParent                     mfrmEdit.Show()                 End If             End If         Catch exc As Exception             LogException(exc)         End Try     End Sub     Protected Overrides Sub DeleteButton_Click(ByVal sender As Object, _     ByVal e As System.EventArgs)         Try             Dim objTerritory As Territory             objTerritory = mobjTerritoryMgr.Item(lvwList.SelectedItems(0).Text)             objTerritory.Delete()             mobjTerritoryMgr.Remove(objTerritory.TerritoryID)             lvwList.SelectedItems(0).Remove()             lblRecordCount.Text = "Record Count: " & lvwList.Items.Count         Catch exc As Exception             LogException(exc)         End Try     End Sub End Class 
end example

Caution

The one thing to note about this code is the mobjTerritory_ObjectChanged method. If you look at the updated block, you will notice that you are not updating the TerritoryID even though it is a value the user can edit. This is one reason using a key of this type is a terrible idea. I cannot stress that enough. By changing the primary key, you have no identifier by which you can determine what value was changed, so you cannot update the value in the list (or any other place where it might be used for that matter). I do not address how to take care of this because it can be complicated (especially if you have a composite primary key), but be aware that primary keys should be values that the user does not have access to change. This makes your life a lot easier.

Creating the frmTerritoryEdit Form

Next, add an inherited edit form to the NorthwindTraders project and call it frmTerritoryEdit.vb. This form should inherit from your frmEditBase form. There are going to be a couple of errors at this point because you have not added your code to the frmTerritoryEdit form. Let's take care of those errors by adding the necessary controls to the edit form and by adding the code you need. When you are done adding controls, the edit form looks like Figure 7-2. Table 7-1 lists the controls and their properties.

Table 7-1: The Territory Edit Form Controls

Control

Name

Text

Style

Form

frmTerritoryEdit

Territory [Detail]

Label

lblID

Territory ID:

Label

lblTerritory

Territory:

Label

lblRegion

Region:

Textbox

txtTerritoryID

Textbox

txtTerritory

Combobox

cboRegion

DropDownList

click to expand
Figure 7-2: Territory edit form

The other controls have already been added by way of the base edit form. Set the tab order according to Figure 7-2. Remember to set the IconAlignment on erpMain property for all of the edit fields to MiddleLeft. Also, set the text alignment for the labels to the bottom right.

Add the following code to the frmTerritoryEdit.vb code module header:

 Option Strict On Option Explicit On Imports NorthwindTraders.NorthwindUC 

Declare a private module-level variable for the Territory object:

 Private WithEvents mobjTerritory As Territory 

Modify the constructor so it reads as follows (note that this is almost identical to the frmRegionEdit form):

 Public Sub New(ByRef objTerritory As Territory)      MyBase.New()      'This call is required by the Windows Form Designer.      InitializeComponent()      'Add any initialization after the InitializeComponent() call      mobjTerritory = objTerritory      If Not mobjTerritory.IsValid Then           btnok.Enabled = False      End If End Sub 

Next, add the code in Listing 7-12 to handle the form's Load event.

Listing 7-12: The frmTerritoryEdit_Load Method

start example
 Private Sub frmTerritoryEdit_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load      Dim DictEnt As DictionaryEntry      Dim objRegion As Region      Dim objRegionMgr As RegionMgr      Try           objRegionMgr = objRegionMgr.GetInstance           For Each DictEnt In objRegionMgr                objRegion = CType(DictEnt.Value, Region)                cboRegion.Items.Add(objRegion)           Next           If mobjTerritory.TerritoryID <> "" Then                txtTerritoryID.Text = mobjTerritory.TerritoryID                txtTerritory.Text = mobjTerritory.TerritoryDescription                cboRegion.SelectedItem = mobjTerritory.Region           End If      Catch exc As Exception           LogException(exc)      End Try End Sub 
end example

First, this method gets a reference to the RegionMgr object and loops through it to add all of the objects to the combo box. Next, it checks to see if this is a new record because if it is a new record, there is no reason to get anything from the object. If it is an existing record, you set the fields so they contain the proper values. Note the following two lines:

 cboRegion.Items.Add(objRegion) . . cboRegion.SelectedItem = mobjTerritory.Region 

As mentioned in a previous chapter, the value used to fill combo and list boxes when adding an object to them is the value returned by the ToString method. Once the value has been added to the combo box, it is easily selectable by setting the SelectedItem property to the object that you want to select. You no longer have to loop through the combo or list box looking for a string.

Tip

As a fun test, you can comment out the ToString method in the Region object and look at what fills the combo box. This is not very helpful, but when you do see it, you will remember what you forgot to do!

At this point, there is just about enough code to be able to bring up the territory list and to be able to open the edit form. Before you can do that, however, you need to modify the frmMain form. In the MainMenu_Click method, add the following Case statement:

 Case "&Territories"     LoadTerritories() 

Next, add a module-level variable for the territory list form as follows:

 Private mfrmTerritoryList As frmTerritoryList 

Finally, add the LoadTerritories routine as shown in Listing 7-13.

Listing 7-13: The LoadTerritories Method

start example
 Private Sub LoadTerritories()      Try          Cursor = Cursors.WaitCursor          mfrmTerritoryList = New frmTerritoryList()          mfrmTerritoryList.MdiParent = Me          mfrmTerritoryList.Show()      Catch exc As Exception           LogException(exc)      Finally           Cursor = Cursors.Default      End Try End Sub 
end example

Up to this point, there is one thing omitted from the code that loads your list forms, and you have probably discovered what it is by now: You can load up multiple list forms for the same item. To ensure there is only one list form for a particular item that is ever loaded, you need to modify your code a little bit. Let's modify the code in frmMain that loads the territory list form. First, change the module-level form variable to be a WithEvents variable. The reason for this is that you need to capture the Closed event that the form generates. Enter the following code to handle the Closed event:

 Private Sub mfrmTerritoryList_Closed(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles mfrmTerritoryList.Closed     mfrmTerritoryList = Nothing End Sub 

Next, modify the LoadTerritories method to check and see if an instance of your variable already exists. Modify the Try block so that it looks like the following:

 If mfrmTerritoryList Is Nothing Then      Cursor = Cursors.WaitCursor      mfrmTerritoryList = New frmTerritoryList      mfrmTerritoryList.MdiParent = Me      mfrmTerritoryList.Show() Else      mfrmTerritoryList.Focus() End If 

Now you are guaranteed that only one instance of your territory list form will ever exist at one time. If a user tries to load the form when it has already loaded, the form will get the focus and be moved to the front of all of the other forms. Now you are ready to run the code.

Before running the code, make sure to rebuild the solution and copy the NorthwindDC and the SharedObjects to the directory that is pointed to by the virtual Internet Information Server (IIS) directory! When you have that done, run the application so that you can examine some of the concepts discussed.

When the application loads, open the Territory screen by selecting Territories from the Maintenance menu. Notice all of the Region entries that say Eastern. Next, close this window and open the Region list screen from the Maintenance menu. Select the Eastern region and edit it so that it reads Eastern1. Close these windows and go back to the Territory list. Notice that everything that did read Eastern now reads Eastern1. All this occurs because you referenced the Region objects instead of instantiating your own.

Note

This is what I meant earlier when I said that even though the property set is ByVal, it is really ByRef in this case!

It is up to you if you want to go back and change Eastern1 to Eastern. Next, select one of the Territory items for editing. Note the combo box values and the selected value. Close all of this and let's go back to adding code to the edit form.

Now you will add the validated events for the three edit fields. These are identical to the one validated event that you created before in the Region edit form, with only a slight difference for the combo box. Listing 7-14 shows the validated events.

Listing 7-14: The Territory Edit Form Validated Events

start example
 #Region " Validate Events"     Private Sub txtTerritoryID_Validated(ByVal sender As Object, _     ByVal e As System.EventArgs) Handles txtTerritoryID.Validated         Dim txt As TextBox = CType(sender, TextBox)         Try             mobjTerritory.TerritoryID = txt.Text             erpmain.SetError(txt, "")         Catch exc As Exception             erpmain.SetError(txt, "")             erpmain.SetError(txt, exc.Message)         End Try     End Sub     Private Sub txtTerritory_Validated(ByVal sender As Object, _     ByVal e As System.EventArgs) Handles txtTerritory.Validated         Dim txt As TextBox = CType(sender, TextBox)         Try             mobjTerritory.TerritoryDescription = txt.Text             erpmain.SetError(txt, "")         Catch exc As Exception             erpmain.SetError(txt, "")             erpmain.SetError(txt, exc.Message)         End Try     End Sub     Private Sub cboRegion_Validated(ByVal sender As Object, ByVal e As _     System.EventArgs) Handles cboRegion.Validated         Dim cbo As ComboBox = CType(sender, ComboBox)         Try             mobjTerritory.Region = CType(cbo.SelectedItem, Region)             erpmain.SetError(cbo, "")         Catch exc As Exception             erpmain.SetError(cbo, "")             erpmain.SetError(cbo, exc.Message)         End Try     End Sub #End Region 
end example

The cboRegion_Validated method uses a combo box object, but notice the line of code that assigns the value in the combo box to the Region value in your Territory object. You need to perform a conversion on the SelectedItem so that you can assign it to the Territory object.

Tip

I have enclosed the validate events in a Validate Events region. It is a good idea to put like groups of methods together into a region so that they do not get in your way—especially when the coding is completed and you are 99-percent positive that there are no errors within that block of code. Who wants to keep looking at the same code when it is not important in the context of what you are trying to accomplish at the time?

Next, add the code for the btnOK.Click method as shown in Listing 7-15. This code is identical to the code in the frmRegionEdit form except that it works on an object.

Listing 7-15: The btnOK_Click Method

start example
 Private Sub btnOK_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnOK.Click      Try           If mobjTerritory.IsDirty Then                mobjTerritory.Save()           End If           Close()      Catch exc As Exception           LogException(exc)      End Try End Sub 
end example

Finally, add the code in Listing 7-16 to handle the BrokenRules and GetBusinessRules events.

Listing 7-16: Handling the Broken Rules and Business Rules Events

start example
 Private Sub mobjRegion_BrokenRule(ByVal IsBroken As Boolean) _ Handles mobjTerritory.BrokenRule      If IsBroken Then           btnOK.Enabled = False      Else           btnOK.Enabled = True      End If End Sub Private Sub btnRules_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnRules.Click      Dim frmRules As New frmBusinessRules(mobjTerritory.GetBusinessRules)      frmRules.ShowDialog()      frmRules = Nothing End Sub 
end example

At this point, you can now add, edit, delete, and print the territories.




Building Client/Server Applications with VB. NET(c) An Example-Driven Approach
Building Client/Server Applications Under VB .NET: An Example-Driven Approach
ISBN: 1590590708
EAN: 2147483647
Year: 2005
Pages: 148
Authors: Jeff Levinson

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net