4.4. Using the Custom Controls


Your custom control (RolodexPanel) will be housed within a form. The base form will be frmRolodex, whose job will be to provide common code for all the specialized forms (e.g., frmCustomerRolodex).

Back in the NorthWindWindows project, add a new form, frmRolodex. Set its size to 976,615. Open the Toolbox and expand the NorthWindControls Components section. Drag a RolodexPanel onto the new form, and drag a label named lblDisplay above it, as shown in Figure 4-6.

Everything in frmRolodex will be shared by all its derived types. You want to factor all the elements common to the derived forms into this form, so they will be as simple (and maintainable) as possible.

You need two members:

 Protected orderedBy As String Protected infoTable As Data.DataTable 

The first, orderedBy, will keep track of the sort order for the data table. The second, infoTable, will hold a reference to a DataTable (e.g., the Customers table).

There are three event handlers you must create: one for when the form is loaded, the second for when the RowFillEvent is fired by the RolodexPanel, and the third for when the ButtonSelectedEvent is fired by the RolodexPanel.

When the form is loaded, you'll call LoadRolodex, a helper method, as shown in Example 4-12.

Figure 4-6. Adding RolodexPanel to frmRolodex


Example 4-12. Rolodex form Load event handler
 Private Sub frmRolodex_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load     LoadRolodex(  ) End Sub 

This method will not be implemented in the base class, but will be implemented in the derived forms:

 Protected Overridable Sub LoadRolodex(  ) End Sub Protected Overridable Sub LoadRolodex(ByVal letter As Char) End Sub 

The second event handler responds to the RowFillEvent of the RolodexPanel, as shown in Example 4-13.

Example 4-13. RowFillEvent event handler
 Private Sub OnFillRows( _ ByVal sender As Object, _  ByVal e As EventArgs) _  Handles RolodexPanel1.RowFillEvent     FillRows    (infoTable) End Sub 

This event handler calls the helper method FillRows, passing in the table to fill the rows from, as shown in Example 4-14.

Example 4-14. FillRows helper method
 Protected Sub FillRows(ByVal infoTable As Data.DataTable)    Dim column As Integer = 0    Dim row As Integer = 0    Me.RolodexPanel1.Clear(  )    Dim loopcounter As Integer    For loopcounter = 0 To Me.RolodexPanel1.NumEntriesPerPage -1       Dim offset As Integer = Me.RolodexPanel1.Vbar.Value + _       (row * 3) + column       If offset >= infoTable.Rows.Count Then          Exit For       End If       Dim dataRow As System.Data.DataRow = infoTable.Rows(offset)       AddEntry(dataRow, column, row)       column = column + 1       If column = 3 Then          column = 0          row = row + 1       End If    Next End Sub 

The effect is to fill the Rolodex Panel with three rows of RolodexEntry objects.

The FillRows method is overloaded. The second version is called by the event handler that responds to an A-Z button being pressed.

 Private Sub OnButtonSelected( _ ByVal sender As Object, _ ByVal e As EventArgs) _ Handles RolodexPanel1.ButtonSelectedEvent     FillRows(Me.RolodexPanel1.CurrentLetter, Me.infoTable) End Sub 

This version of FillRows takes the letter to search for within the data (as well as the DataTable containing the data), as shown in Example 4-15.

Example 4-15. Overloaded version of FillRows helper method
 Protected Sub FillRows( _ ByVal letter As Char, _ ByVal infoTable As Data.DataTable)    Dim offset As Integer = 0    Dim orderByName As Char = CType("A", Char)    For Each dr As Data.DataRow In infoTable.Rows       orderByName = dr(orderedby).ToString(  ).ToUpper(  )(0)       If orderByName >= letter Then          Exit For       End If       offset = offset + 1    Next    Me.RolodexPanel1.Vbar.Value = offset End Sub 

For a description of how the If statement statement works in this code, please see the step-by-step description of clicking on a letter, later in this chapter.


Finally, the code that will be shared by the LoadRolodex override of all the derived forms is factored into the DoLoad method of the base class, shown in Example 4-16.

Example 4-16. DoLoad method DoLoad method
 Protected Sub DoLoad( _ ByVal count As Integer, _ ByVal letter As Char, _ ByVal infoTable As Data.DataTable)     Me.RolodexPanel1.Vbar.Maximum = count     Me.lblDisplay.Text = count.ToString(  ) + " records "     Me.RolodexPanel1.Vbar.Value = 0     FillRows(infoTable) End Sub 

4.4.1. Building the Specialized Forms

With the base form in place, you're ready to derive a specialized form: frmCusto-merRolodex.

Right-click on the NorthWindWindows project and choose Add New Item and select Inherited Form. Name the new form frmCustomerRolodex.vb. You are then presented with the InheritancePicker. Select frmRolodex and press OK. A new form is created that inherits from frmRolodex named frmCustomerRolodex.

Notice that the panel and label are already in place (though the label may be invisible because we set its text to blank). You need access to the CustomersTableAdapter that you created earlier. Look in the toolbox and open the section marked NorthWindWindows Components. Drag the CustomersTableAdapter and the NorthwindDataSet to your form. Rename the dataset instance from NorthwindDataSet1 to NorthwindDataSet and CustomerTableAdapter1 to CustomerTableAdapter.

You want this form shown when the user clicks All Customers from the Welcome page. Go to btnAllClick in Welcome.vb and modify the btnAllClick method to invoke this method if the button's text is All Customers or if the menu contains the word Customers in the text, as shown in the bold code in Example 4-17.

Example 4-17. Modifying the AllClick event handler
 Private Sub btnAllClick( _ ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles btnAllCustomers.Click, btnAllSuppliers.Click, _ btnAllEmployees.Click, btnAllOrders.Click, mnuEmployeesShowAll.Click, _ mnuCustomersShowAll.Click, mnuOrdersShowAll.Click Dim txt As String = String.Empty If TypeOf sender Is Button Then     txt = CType(sender, Button).Text ElseIf TypeOf sender Is ToolStripMenuItem Then     txt = CType(sender, ToolStripMenuItem).Name End If Dim oldCursor As Cursor = Me.Cursor Me.Cursor = Cursors.WaitCursor If txt.Contains("Customers") Then     Dim rolodex As frmRolodex = New frmCustomerRolodex(  )     rolodex.Show(  ) Else     MessageBox.Show(txt + _     " not yet implemented", "Not Yet Implemented", _         MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End If Me.Cursor = oldCursor End Sub 

Now you can go back to frmCustomerRolodex and override the three overridable methods from the base form. The first is LoadRolodex, which is overloaded. The code is shown in Example 4-18.

Example 4-18. Overriding the Rolodex form Load event handler
 Protected Overrides Sub LoadRolodex(  )    LoadRolodex(CChar("A")) End Sub Protected Overrides Sub LoadRolodex(ByVal letter As Char)    CustomersTableAdapter.Fill( _    CType(Me.NorthwindDataSet.Tables("Customers"), _    NorthWindWindows.NorthwindDataSet.CustomersDataTable))    Dim dataTable As NorthwindDataSet.CustomersDataTable = _        CustomersTableAdapter.GetData(  )    Dim count As Integer = dataTable.Rows.Count    Me.infoTable = dataTable    Me.orderedby = "CompanyName"    DoLoad(count, letter, infoTable) End Sub 

In the second overload (the one that takes a letter), you call the Fill method on the CustomersTableAdapter, passing in the Customers table you extract from the NorthwindDataSet variable you just added to the form.

Your only other override is of AddEntry , shown in Example 4-19. This method is very specific to customers. It is also tightly coupled with the Customers table (it knows what values to extract) and with the RolodexCustomerEntry (it knows what values to set). It is, in many ways, the bridge between the RolodexCustomerEntry and its underlying table.

Example 4-19. Overriding the AddEntry method
 Protected Overrides Sub AddEntry( _ ByVal dataRow As System.Data.DataRow, _ ByVal column As Integer, _ ByVal row As Integer)    Dim entry As NorthWindControls.RolodexCustomerEntry = _        New NorthWindControls.RolodexCustomerEntry(  )    Dim companyName As String = String.Empty    Dim contactName As String = String.Empty    Dim phone As String = String.Empty    Dim fax As String = String.Empty    If IsDBNull(dataRow("CompanyName")) = False Then       companyName = CStr(dataRow("CompanyName"))    End If    If IsDBNull(dataRow("ContactName")) = False Then       contactName = CStr(dataRow("ContactName"))    End If    If IsDBNull(dataRow("Phone")) = False Then       phone = CStr(dataRow("Phone"))    End If    If IsDBNull(dataRow("Fax")) = False Then       fax = CStr(dataRow("Fax"))    End If    entry.LoadValues(companyName, contactName, phone, fax)    entry.Left = Me.RolodexPanel1.StartX + _        (column * Me.RolodexPanel1.XIncrement)    entry.Top = Me.RolodexPanel1.StartY + _        (row * Me.RolodexPanel1.YIncrement)    AddHandler entry.EntrySelected, _        AddressOf Me.RolodexPanel1.entry_click    Me.RolodexPanel1.Add(entry) End Sub 

4.4.2. Displaying the Rolodex, Step by Step

The order of operations is critical here. The very best way to see this in action is to use your debugger and to set break points on the following methods:

  • Welcome.vb: btnAllClick

  • frmCustomerRolodex: all three methods

  • frmRolodex: frmRolodex_Load, FillRows (both overloads), and DoLoad

  • RolodexPanel: RolodexPanel_Load

  • RolodexCustomerEntry: Load_Values

When you ask to see all the customers by clicking on the All Customers button, the btnAllClick method is called in Welcome.vb. The button is examined and since its text is All Customers, the frmCustomerRolodex is created and shown.

When frmCustomerRolodex is loaded, the LoadRolodex method runs, fills the CustomersDataTable in the NorthWindDataSet, and then sets the member variable infoTable to the CustomersDataTable. The DoLoad method is then called in the base class, frmRolodex.

DoLoad sets the vertical scrollbar maximum and minimum values, sets lblDisplay.Text, then calls FillRows, passing in the CustomersDataTable. FillRows populates the three columns by extracting one row from the data table (Customers) and calling AddEntry.

AddEntry creates a new RolodexCustomerEntry object and sets its lblCompanyName, lblContactName, lblPhone, and lblFax based on the data in the DataRow.

It then sets the position (the column and row) of the entry and, most importantly, it adds an event handler for that entry. When the entry fires its EntrySelected event, you want the event to be handled by the enTRy_click method of the Rolodex Panel.

 AddHandler entry.EntrySelected, _     AddressOf Me.RolodexPanel1.entry_click 

The entry is then added to the panel. This process repeats for as many entries as will fit in the form (defined as RolodexPanel.NumPageEntries). Once completed, FillRows is finished and the form is displayed.

4.4.3. Clicking on an Entry

When you click on an entry, it is lit up as red. The best way to see how this works is to put break points on:

  • RolodexCustomerEntry: InternalClick, SetSelectedProperties

  • RolodexEntry: InternalClick, Selected Set Accessor

  • RolodexPanel: entry_click

When the user clicks on an entry, that click is captured by RolodexCustomerEntry.InternalClick. It invokes MyBase.InternalClick, passing in a reference to itself. The base method raises the EnTRySelected event, placing a reference to the RolodexEntry that was clicked into the sender argument.

RolodexPanel.entry_click handles that event and deselects every one of its controls. It then sets Selected to TRue on the one RolodexEntry that was passed in as sender. This invokes the Selected accessor on that Rolodex entry, which calls SetSelectedProperties.

SetSelectedProperties is overridden in RolodexCustomerEntry. When the item is not selected, its lblCompanyName background is set to Silver. When it is selected, the background is set to Red.

4.4.4. Walking Through a Letter Button Click

To see what happens when a Letter button is clicked, set break points in:

  • RolodexPanel: LetterButtonClick, LoadRolodex, and vBar_valueChanged

  • frmRolodex: OnButtonSelected, FillRows

Click on the letter T. The LetterButton_Click method is invoked. The result of this is to invoke LoadRolodex (passing in the letter), which sets the current letter, and then to raise the event ButtonSelectedEvent.

That event is caught by frmRolodex, which invokes the FillRows method, passing in the current letter and the data table. FillRows iterates through the rows until it finds a name that begins with a letter equal to or greater than the requested name, at which time it sets the vertical scrollbar value to the offset.

Setting the vertical scrollbar's value causes the vbar to raise the ValueChanged event, which you set in RolodexPanel1_Load to be handled by vbar_ValueChanged. That, in turn, raises the RowFillEvent, passing in the Rolodex Panel itself).

The RowFillEvent is handled by OnFillRows in frmRolodex, which calls the other FillRows method, passing in the DataTable. FillRows extracts the offset from the vertical scrollbar and creates the entries, as you saw earlier, filling in the panel, as shown in Figure 4-7.

Figure 4-7. Running the completed Rolodex




Programming Visual Basic 2005
Programming Visual Basic 2005
ISBN: 0596009496
EAN: 2147483647
Year: 2006
Pages: 162
Authors: Jesse Liberty

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