Using UI to Store and Manipulate Data Is Not a Good Idea

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?

7 thoughts on “Using UI to Store and Manipulate Data Is Not a Good Idea

  1. Agree 100%. Just wish Xojo had a listbox widget that worked like iOS’ UITableView or Einhugur’s DataGrid.

  2. Great post Bob. I agree 98%. There’s probable some exception to what you stated, but most of the time what you stated is very important. For instance, if you were loading a bunch of data into a listbox you’d end up storing it twice.

    In the case of using a ListBox and Detail fields, I’d also suggest minimizing how much data is loaded in the inbox. In the case of Contacts, you might only need the Company Name, First Name, and Last Name along with the Contact ID in the RowTag. Then on click of the row, a second query could load the details with another query using the Contact ID.

    • There are always exceptions. 🙂

      Windows apps tend to load *everything* into a grid, for better or worse, and let the user modify everything from the grid. Mac and Linux apps tend to go with the List view and details view.

      Is one better than the other? Debatable, but it really depends on the target and audience. An accounting app can be done either way but on Windows it tends to be grid only.

  3. my projects often have constants in the window
    kColumnFirstName
    kColumnLastName
    and so on on for the normal fields.
    And for the cellTag also column constants:
    kColumnTagIcon
    kColumnTagTotalSeconds
    so I often have a date displayed in a cell and the celltag has the total seconds or other value to sort it. RowTag is often the record ID from database. Could also be an object for a data class. But a lot of listbox don’t need that class as they only have a few values which are int he cells anyway.

  4. YES! Absolutely split UI and the logic. The UI might include formatting rules, but the data object should do all the validation. Any changes made by the user get fed by the UI to the data object and any errors fed back to the control. That way (a) changes only ever need to be made in one place, and (b) it maximises the possibility of reuse of both parts into other uses.

Comments are closed.