Each row of my listbox has a rowtag containing the object which has all the data for this row. Call it a RowObject. The RowObject needs to sometimes update its row with new data as external data comes in.
How can the RowObject know which row to update?
I see either:
a) Everytime there is a sort or insert, we cycle through the entire listbox contents and update each and every RowObject with a new row number. Ouch.
b) Everytime an update is needed, search every row until you find this RowObject. Ouch.
Am I missing some fundamental way of updating a listbox with changing external data?
I realize I was going about this wrong. I was having the object update the listbox row whenever data changed regardless of whether it’s in view.
What I should do instead is whenever a celltextpaint even occurs, grab the most recent data for that event and apply it to that cell.
@Karen Atkocius : I did a quick sample project and if I put this in the celltextpaint event, it seems to update the row without needing invalidate.
Function CellTextPaint(g As Graphics, row As Integer, column As Integer, x as Integer, y as Integer) As Boolean
me.cell(row, column) = "Boo! New data!"
return false
End Function
[quote=165590:@Stephen Dodd]@Karen Atkocius : I did a quick sample project and if I put this in the celltextpaint event, it seems to update the row without needing invalidate.
[/quote]
DO NOT COUNT ON THAT. IT WILL NOT ALWAYS BE THE CASE!!!
To speed up listbox display, unless a cell is marked dirty by the framework it not redrawn. In this case you must be doing something which is dirtying it.
the thing is you want only the changed cells to actually redraw
so you need some mechanism for an object in a rowtag to tell the listbox at they very least that it changed so that one row can be redrawn
you can do it with an observer pattern that you can implement in one of many ways
you could do this with add handler - but you still have to hunt the visible rows for the one that raised the event the handler is attached to
and you do have to make sure you remove handlers
or you could use something more broad that is more like a notification center for your app
again you still need to locate the row that changed to make sure you invalidate just that row
@Norman Palardy If I set the value for the cell on every celltextpaint event, am I causing a lot more work for the listbox than if I smartly only set it if the data has changed?
@Karen Atkocius Well, my code didn’t break by adding the above. So I tried limiting my listbox to 1 row and adding a beep during CellTextPaint. It didn’t repeatedly beep at me which suggests that somehow it doesn’t loop during invalidate.
@Norman Palardy With the beep test above, it seems that invalidating doesn’t actually cause the routine to fire more than once. The next question is does changing the values during CellTextPaint cause extra work? I suspect not really as it has to do a paint event anyways.
The big problem though with relying on CellTextPaint to update your data is that it only fires when the user scrolls or similar. If he is just staring at the listbox the data won’t change. And if the data changes, we have to find the right row to update. Doing listbox.invalidate everytime data changes seems to work (in conjunction with CellTextPaint) but I’m not sure how expensive than is.
[quote=165616:@Stephen Dodd]@Karen Atkocius Well, my code didn’t break by adding the above. So I tried limiting my listbox to 1 row and adding a beep during CellTextPaint. It didn’t repeatedly beep at me which suggests that somehow it doesn’t loop during invalidate.
[/quote]
That code won’t break it BUT it will keep looping. My code proves it. When you add teh code does not you break into teh debugger if you wait long enough? I you have a slow machine change teh 1000 to 1000…
The comment out the assignment and run again and wait and you will see you don’t break into the debugger.
At this point I think you have enough info to understand what is going on so i will let you think about it.
I appreciate your help Karen. Strangely, if a single row listbox with invalidate in the celltextpaint and have it static count to 10, it never breaks into the debugger. Tried on Mavericks. Maybe Windows is different?
Interesting. I guess it’s the difference between the renderer on 10.9 vs 10.10 or maybe even retina resolution (which I have). I think the important thing is it does infinite loop for you so some workaround is needed to prevent the loop.
Turns out using listbox.invalidate to cause listbox.CellTextPaint to fire to update your data doesn’t work on Windows.
That looks like a pretty awesome listbox project you have! Nice.
Strange about the listbox.invalidate. The previous example
updates in real time on Mac and just sits there until scrolled on Windows even if you add the invalidate line to CellTextPaint.
But it’s no biggie. I’m not going to use listbox.invalidate. I think in the end the best solution is going to be to search my listbox for the appropriate row to update.