Set PopupMenu ListIndex

In my (very simple) application, I have a popupmenu, that contains a short list of monthly bill descriptions like so :

Broadband
Council Tax
Credit Card
Home Insurance
Utilities

(There are others but I’ve shortened the list for the purpose of showing here).

In the rowtag for each item above, I have added the primary key ID (Integer) from the SQLite table that contains the information. So building it up, it now looks like this:

Rowtag       Text            Popupmenu Listindex
------       ----            -------------------
8            Broadband       0
4            Council Tax     1
6            Credit Card     2
9            Home Insurance  3
3            Utilities       4

Rowtag values then, are always unique but not always in numeric order, and will rarely, if ever, match the listindex value of the popupmenu.

In the program, I also have a property called ‘AccountID’ which is set elsewhere when a particular account is selected, and contains the same primary key ID as described above.

The idea with the code I’m about to show you is to set the listindex of the popupmenu to match the selected bill description, by comparing the rowtag to the AccountID.

Going on the above information, if the user selects for example the ‘Home Insurance’ account elsewhere on the screen, the AccountID property is set to a value of 9.

The code I have to do this is in a method as shown below :

SetTransactionAccount(AccountID As Integer)
  For i As Integer = 0 To wMain.pmTransactionAccount.ListCount-1 ' zero based control, so start at 0 and subtract 1 from the total
    If wMain.pmTransactionAccount.RowTag(i)=AccountID Then       ' does the rowtag match the AccountID I'm interested in ?
      wMain.pmTransactionAccount.ListIndex = i                   ' if it matches, set the ListIndex based on the ListCount value
      Exit For i                                                 ' Exit the method since no further checks are required
    End If                                                       ' This comparison is finished
  Next                                                           ' Check the next ListCount item in the popupmenu

The code above works; my 2 questions are:

  1. Is this the correct way to set the popupmenu listindex to match the selected account ?
  2. Is ‘Exit For i’ the correct way to gracefully exit the method, since we dont want to do any more checks once the first (And only) match is found ?

Uncommented code (It didn’t wrap as much when I typed the message) :

  For i As Integer = 0 To wMain.pmTransactionAccount.ListCount-1
    If wMain.pmTransactionAccount.RowTag(i)=AccountID Then
      wMain.pmTransactionAccount.ListIndex = i
      Exit For i
    End If
  Next

That’s essentially the way I handle similar situations.

I do it in a similar way, except I have it as an extension method to the popup. That way I can just set it like

myPopup.SetText( TextToDisplay )

for any popup that needs it.

Thanks guys, at least I know Im on the right track. Its worked so far 100% in every test.

Markus, any chance you could share the way you did that? Im not familiar with extending that way just yet.

From one xDev Tips&Tricks column:

Whenever I see where a little effort could provide big rewards I want to see it implemented. As a beginner I stayed away from “advanced” stuff like Extends. But there is really nothing to it - it is simply a way to add a method or function to the build-in classes like shown in these two examples:

[code]Function Contains(Extends TextContainer as String, TextToFind as String) as Boolean
return TextContainer.InStr( TextToFind ) > 0
End Function

Function IsEmpty (Extends aString As String) as Boolean
return theString = “”
End Function[/code]

Now writing

 if myText.contains("Xojo") then

or

if MyDocument.text.IsEmpty then

certainly makes your code much easier to read and maintain than writing

 if InStr( myText, "Xojo") > 0 then

or

 if MyDocument.text = "" then

From another xDev Tips&Tricks column:

If you are using PopupMenus then often you have to set the text of the PopupMenu to some value. The code is often like this:

for i as integer = 0 to pm.ListCount-1 if pm.list(i) = sSomeText then pm.ListIndex = i exit end next

and after writing it a few times you might have put it into a method like me. However as Bob Keeney points out in his blog (http://www.bkeeneybriefs.com/2014/10/subclassing-vs-extends-vs-containers/) it is much nicer to do this as an extension:

Sub SetText(extends pm as PopupMenu, assigns s as String) for i as integer = 0 to pm.ListCount-1 if pm.list(i) = s then pm.ListIndex = i return // exit end next // what if text is not in the popup menu? MsgBox "I tried to set <" + pm.Name + "> to <" + s + "> but it is not one of the available choices. Please inform the developer of this." End Sub

This way it becomes part of the AutoComplete list and you simply call it like this:

pmFont.setText = sSomeText

What is this “assigns”? It means that we pass the string in with the “assignment operator” =. We could also have written the method declaration as

Sub SetText(extends pm as PopupMenu, s as String)

in which case we would call the function by passing an argument like this

pmFont.setText( sSomeText )

or without brackets like this

pmFont.setText sSomeText

But what if the text is not in the popup menu because you made a typo somewhere? In this case the popup menu will just stay as it is and not change to the new text. This is another one of those hard to find errors as no error is being raised. To account for that you could raise an error exception or just call a message box and put an error message up. Note that you need to change the exit from Bob’s original tip to return, as exit only exits the loop while return exits the method.

Thankyou Markus, I’ll look at this for my stuff.

I see its come from an xDev article. Any idea how long that takes when you get the Omega Bundle ? I’ve had some of the licenses and stuff come through but not all of them yet.

You should have it all within a few days (certainly the xDev). Don’t forget to check your spam folder too!

If you haven’t gotten it after 3 or 4 days then maybe send Marc Zeedar an email

Just to correct the formatting (as I can’t correct the original anymore):