I’ve fielded a number of questions from developers over the years asking about the Xojo Listbox. They question is if it’s a good idea to store and manipulate data in the Listbox. While it’s possible, I say the answer is no, the Listbox is NOT a good place to store and manipulate data. It’s also a poor place to put your business logic.
The Listbox is a user interface element. It’s job, if you will, is to present data to the user in a grid. Along the way you get the added advantage of resizable columns, sortable columns, the ability to do things in the cell with text, checkboxes, and even doing your own custom drawing and handling. It conveniently allows us to stash data in row, column, and even cell tags and therein lies the delicious dilemma for users that need to manipulate data.
It’s common to see Xojo developers load a listbox and while it’s loaded manipulate all data in its cells and cell tags. Their listbox events are filled with code to do things to other cells, and tags, and there is often a lot of code for business logic in them. Then, when it’s all done, they save it off in whatever format they’re using. This is all fine but it’s a royal pain to debug because most people don’t think about using a constant value, say kAverageValue, but instead say me.cell(iRow, 5) = str(NewAverage). To be honest this works well until you add a new column. Then, all of your code for the cells to the right of the new column is wrong and you won’t know it until you test.
Another thing that I’ve seen happen is conversion errors. The developer stashes a numeric value in the listbox cell and formats it. Then has to go through the process of converting it back to a number for use in the database or file. This often leads to issues that, again, can be tricky to track down.
Instead, we recommend using a data class that represents each row of data. The whole list of data can be thought of as an array of data and we store each row in the row tag property. What it boils down to is that when you’re start working with the data you manipulate the data in the data class rather than in the UI. Then you update the UI from the data class. The heart of it is your data class and it’s there you should put your business logic. If cell 5 can’t be a negative number if cell 1 is greater then 100 it might make more sense to put the validation code in the data class rather than in the listbox itself. That way you can do validation logic based on class property names rather than listbox row and column values.
If iAverage > 100 and iSetPoint < 0 then
is easier to understand than
if me.cell(row, 1).val > 100 and me.cell(row, 5).val < 0 then
The other thing that’s bad about depending upon the UI to store your data is now you are tied to that control. I know developers that have invested a lot of time using the StyleGrid and when it wasn’t updated they spent a lot of time rewriting it for the listbox. Some rewriting is inevitable, but if you can uncouple your data and your UI it’s much easier to move to another control later on.
We use ActiveRecord a lot and whenever possible we put our business logic in it rather than the listbox. Does this mean that we get rid of all logic in the listbox? No! If column 0 can’t be negative, ever, then by all means put that logic in there. But if the value in column 0 depends on another column we try to put it in the ActiveRecord data class. The listbox simply becomes the input and display mechanism for the class.
Am I suggesting your go rewrite your listbox today? Absolutely not, but perhaps the next time you want to make your listbox jump through hoops, perhaps you uncouple the data and put your business logic in a data class rather than in the listbox. You might like the results.
Thoughts? Do you agree or disagree?