Atlanta Custom Software Development 

 
   Search        Code/Page
 

User Login
Email

Password

 

Forgot the Password?
Services
» Web Development
» Maintenance
» Data Integration/BI
» Information Management
Programming
  Database
Automation
OS/Networking
Graphics
Links
Tools
» Regular Expr Tester
» Free Tools

Mutually exclusive list boxes

Total Hit ( 2020)

Rate this article:     Poor     Excellent 

 Submit Your Question/Comment about this article

Rating


 


Many Windows programs use two adjacent list box controls to let the user select a number of items from a list of available values; such list boxes are mutually exclusive, in the sense that a given item always appear in the list box on the left (available items) or in the list box on the right (items that have been selected so far). While it is not difficult to implement a simple VB program that does the trick, a minor problem is that in the real world you have to preserve the same logical ordering of the items enforced in the original list box, and this has often nothing to do with the alphabetical order. For instance, you might offer a list of months for the user to select from, and wish that selected months appear in the rightmost list box in the same logical (i.e. chronological) order expected by the user. Another point you should deal with are list box controls that support multiple selections. Here is a routine that takes all these details into account:

Click here to copy the following block
Sub MoveListItem(sourceList As ListBox, destList As ListBox, _
  Optional itemIndex As Variant)
Dim index As Long
Dim thisItemData As Long
  
If Not IsMissing(itemIndex) Then
  ' use itemIndex if not omitted
  GoSub MoveListItem_Sub
ElseIf sourceList.MultiSelect = 0 Then
  ' else use current item
  itemIndex = sourceList.ListIndex
  GoSub MoveListItem_Sub
Else
  ' this is a multi-selection listbox
  ' loop over all selected items
  ' NOTE that we cannot use a simple For..Next loop
  ' because while we remove items their index changes
  itemIndex = 0
  Do While itemIndex < sourceList.ListCount
    If sourceList.Selected(itemIndex) Then
      GoSub MoveListItem_Sub
    Else
      itemIndex = itemIndex + 1
    End If
  Loop
End If
Exit Sub
  
MoveListItem_Sub:
If itemIndex < 0 Then Exit Sub
thisItemData = sourceList.ItemData(itemIndex)
If thisItemData = 0 Or destList.Sorted = True Then
  ' if there is no associated ItemData append this
  ' element to the end or exploit curret Sort order
  destList.AddItem sourceList.List(itemIndex)
Else
  ' else we must search the proper location
  ' in the destination listbox
  For index = 0 To destList.ListCount - 1
    ' loop until we find an item with higher ItemData
    If destList.ItemData(index) > thisItemData Then
      ' add new item in that position
      destList.AddItem sourceList.List(itemIndex), index
      ' do not forget the associated data
      destList.ItemData(index) = thisItemData
      ' signal that we did the insert
      thisItemData = 0
      Exit For
    End If
  Next
  If thisItemData Then
    ' this happens when the element goes to the end
    destList.AddItem sourceList.List(itemIndex)
    destList.ItemData(destList.ListCount - 1) = thisItemData
  End If
End If
' remove from source listbox
sourceList.RemoveItem itemIndex
Return

End Sub

You can call this routine specifying the index of the item you with to move, or you can omit it. In this latter case the routine behaves differently if the source list box supports multiple selections (in which case all selected items are moved) or not (in which case only the current item is moved). The insertion of a new item in the destination list box is a bit tricky, because the routine also checks if the source item has any ItemData value associated to it, and if so it uses this value to search for the correct position in the list box. While this routine does all the actual work, you still have to build a reasonable user interface. In this code example I build a couple of list box controls - named List1(0) and List1(1) - plus two command buttons. You can move items by double clicking on any item on either list box, or use the Add and Remove buttons:

Click here to copy the following block
Private Sub cmdAdd_Click()
  MoveListItem List1(0), List1(1)
End Sub

Private Sub cmdRemove_Click()
  MoveListItem List1(1), List1(0)
End Sub

Private Sub List1_DblClick(index As Integer)
  MoveListItem List1(index), List1(1 - index)
End Sub

At this point you only have to load some data in the leftmost list box control, which you usually do in the Form_Load event. For instance, you might offer the list of months

Click here to copy the following block
Private Sub Form_Load()
  With List1(0)
    .AddItem "January"
    .AddItem "February"
    .AddItem "March"
    .AddItem "April"
    .AddItem "May"
    .AddItem "June"
    .AddItem "July"
    .AddItem "August"
    .AddItem "September"
    .AddItem "October"
    .AddItem "November"
    .AddItem "December"
  End With
End Sub

Obviously, it makes no sense to use sorted list boxes in this cases. In order to enforce this same ordering even when items are moved to another list box (and possibly back to the original one), you should assign a progressive ItemData value to each element. I have prepared a short routine that does just that, and that you can easily reuse in all your projects:

Click here to copy the following block
Sub InitItemData(sourceList As ListBox)
  Dim i As Long
  For i = 0 To sourceList.ListCount - 1
    sourceList.ItemData(i) = i + 1
  Next
End Sub


Submitted By : Nayan Patel  (Member Since : 5/26/2004 12:23:06 PM)

Job Description : He is the moderator of this site and currently working as an independent consultant. He works with VB.net/ASP.net, SQL Server and other MS technologies. He is MCSD.net, MCDBA and MCSE. In his free time he likes to watch funny movies and doing oil painting.
View all (893) submissions by this author  (Birth Date : 7/14/1981 )


Home   |  Comment   |  Contact Us   |  Privacy Policy   |  Terms & Conditions   |  BlogsZappySys

© 2008 BinaryWorld LLC. All rights reserved.