Saturday, February 27, 2010

Loop Through Controls in VB


A little info about the tool to the left that I'm building then I'll get to the point:

This Attribution Assistant (screenshot of version 1) allows a user to quickly apply attribution to selected features in ArcMap.  Say you're attributing a huge dataset of streams (my current project) and they need to be designated either a "river," a "stream," or a "canal."  One can open an editing session and type in the values as they're hilighted, or for several at a time (a bit more efficient) a user can right click on the in the attribute table, and use the Field Calculator to do some en-masse attribution, but she or he will still need to change that one value over and over again.  Back and forth... Kill me.

Instead, select the layer of interest, then select the field that will hold the attribution, and add up to 16 text boxes for possible values (it starts with just one row, but the screenshot is expanded to 16 for the sake of screenshots...).  Then select some features and click the calculator button that corresponds with the proper value.  That's it.  One click attribution.

The check boxes to the right disables the corresponding text box and delete button so a user doesn't accidentally change/remove values.  Here's the problem though.  For version 2, there will be a "Check All" check box at the top that will let the user - that's right - select/unselect all check boxes at once.  The best way to do this is to loop through each check box control and set its value to False.

Easier example to begin:
  • All text boxes should be reset when the the dataset is changed or the form is "reset" for other possible reasons.
Originally, the Reset procedure/subroutine had 16 lines which manually erase each text box:

‘Reset all text boxes to null or  “”
txtValue01.Text = ""
txtValue02.Text = ""
txtValue03.Text = ""
txtValue04.Text = ""
txtValue05.Text = ""
txtValue06.Text = ""
txtValue07.Text = ""
txtValue08.Text = ""
txtValue09.Text = ""
txtValue10.Text = ""
txtValue11.Text = ""
txtValue12.Text = ""
txtValue13.Text = ""
txtValue14.Text = ""
txtValue15.Text = ""
txtValue16.Text = ""

This works, but it's lame.  Here's a better way, explained below:

‘This is faster
Dim cControl As Control
For Each cControl In Me.Controls
........'Look for text boxes only
........If TypeName(cControl) = "TextBox" Then
............cControl.Text = ""
....End If

Next cControl
[Be sure to remove the dots (....) used to format the above code]

- Start by creating an object named cControl (or whatever) As a Control.
- Make a For Each loop that will loop/search through all controls (buttons, text boxes, etc. see my VB Cheat Sheet) in the form.
- Begin to target which specific controls you want to change.  In this case all text boxes in the form should be changed, but if there were more text boxes, you can add more parameters to a query.  For instance, all text boxes with a certain .Tag or .Name.  Use logic operators (like And, Or, etc.) to add to the query.

A (just slightly) more difficult example:

I also want to set .Tabstop = False for some of the text boxes so a user can hit the tab key to move the cursor to the next available text box.  The problem is that I don't want the user to tab to a box that is out of view. (I cheated.  When the form initializes, there seems to be only one row of attribution controls, but there are 16.  The form just gets bigger and the next row of controls are initialized.  They're really there the whole time though.)

So there's some code to take care of turning the .Tabstop property on, but let's just focus on turning that off as well.  I'll also include another parameter in the query to find the exact controls, highlighted below:

‘Loop through controls
Dim cControl As Control
For Each cControl In Me.Controls
........'Look for specific text boxes
........If TypeName(cControl) = "TextBox" And _
............cControl.Name Like "txtValue*" Then
............cControl.Text = ""
............cControl.Tabstop = False
....End If
Next cControl
[Be sure to remove the dots (....) used to format the above code]


    No comments: