I have a listbox with a list of words. When I scroll down and select one I redraw the contents making a slight change to the selected word. At the moment it selects the first word at the top after the repopulation of the listbox.
How do I get it to show the contents looking like it is in the same position as before the update?
You could retain and restore the position and selection, or you could not RemoveAllRows and only update what’s necessary.
Hi Tim,
In Cellclicked event
me.ScrollPosition = row + ?
Puts me back to seeing the last click value at the top of the listbox but how do I know how may rows are currently displayed in the listbox on the current window so I can calc?
To restore the original scroll (if the selection isn’t at the top), retain the original ScrollPosition.
var iPos as Integer = me.ScrollPosition
me.RemoveAllRows
// Repopulate
me.ScrollPosition = iPos
You can know the number of rows with Listbox.RowCount
. If you mean that you want to know how many rows tall the Listbox is,
Listbox.Height / Listbox.DefaultRowHeight
Hopefully one of those three ideas helps you solve your issue. I’m not entirely sure I’m understanding what you’re looking for. If I’m reloading a list and want it to return to the original position I use the first method.
Thanks Tim
What I usually do is populating an array with RowIDs.
These IDs are record IDs I store in the RowTag value.
I get these IDs right before I remove all rows.
When populating the Listbox again, with data, I do two things:
- Check if the ID of the (new) row data is in this array. And set the RowSelectedAt to True, if it is.
- Set a row-index variable if the first selected row is found.
If this second variable is set, I use that to that row index variable to set the scroll position.
In a Method “PopulateList()” I usually have something like this:
// sel() is an array that will hold all RowIDs of the selected rows.
Var id, sel() As String
Var row As Integer
// lb is a listbox
If lb.SelectedRowCount = 1 Then
row = lb.SelectedRowIndex
id = lb.RowTagAt(row).StringValue
sel = Array( id )
ElseIf lb.SelectedRowCount > 1 Then
// iterate through the list, to get all the
For row = lb.SelectedRowIndex To lb.LastRowIndex
// if a row is selected, add its ID to the "sel" array
If lb.RowSelectedAt(row) Then
id = lb.RowTagAt(row).StringValue
sel.Add id
End
Next
End
// Now we have a collection of all the selected rows, we can clear the list.
lb.RemoveAllRows
// sRow will be the row index of the first selected row in the list.
Var sRow As Integer = -1
Var rs As RowSet = getOrders // GetOrders is a function that returns a RowSet with data from a database.
If rs.RowCount = 0 Then Return // exit when there are no rows in the RowSet
Var isSel As Boolean
For Each dRow As DatabaseRow In rs
// get the ID for the record
id = dRow.Column("id").StringValue
// in case the id is found in the "sel" array, set the isSel variable to True
isSel = (sel.IndexOf( id ) > -1)
// Add a row to the listbox, and set it's rowID in the RowTag value
lb.AddRow dRow.Column("OrderNumber").StringValue, dRow.Column("OrderDescription").StringValue
row = lb.LastAddedRowIndex
lb.RowTagAt(row) = id
// Set the selection of the row
lb.RowSelectedAt(row) = isSel
// if the row is selected, and the sRow value is still < 0, set the sRow value to the current RowIndex
If isSel And sRow < 0 Then sRow = row
Next
// This line of code will simply set the scroll position. After this, populating the listbox is done.
' If sRow > -1 Then lb.ScrollPosition = sRow
// But lets get fancy, and set the scroll the list, so that the first selected row is in the middle of the view.
// That's why I commented-out the line of code above
Var rowHeight As Integer = lb.DefaultRowHeight
Var lbHeight As Integer = lb.Height
If lb.HasHeader Then lbHeight = lbHeight - lb.HeaderHeight
// Calculate the visible rows in the list. And get the offset, so that we can scroll to the right scroll position.
Var visibleRows As Integer = lbHeight / rowHeight
Var rowOffset As Integer
If visibleRows > rs.RowCount Then
rowOffset = visibleRows / 2
End
// Adjust the sRow so that the first selected row appears in the middle of the list.
// But make sure it is never lower than 0… that's the Max() function is for.
sRow = Max(sRow - rowOffset, 0)
lb.ScrollPosition = sRow
Thanks Edwin for the input… next level
Yeah, not really a 101 kind of input. Sorry about that…
The real next-level would be to not set the selected row in the middle, but keep that selected row at the same position as it was before.
Like, if the first visible selected row is the 4th from the top, scroll the list so that selected row is again at that 4th position. No matter how many rows were added or deleted before or after that row.