Multi-column Hierarchical ListBox

More or less based on the example in the xojo help docs under listbox, I have a working hierarchical listbox.

The problem is I would like for the top level to have more than one column. Once I change the number of columns on the ListBox to 3 (or 2) the sub-groups that are hidden until the disclosure triangle is clicked automatically display in the other 2nd row.

Is there no way to have a multi-column hierarchical listbox?

And then the follow-on would be, is there a way for the sub-groups that display when the disclosure triangle is clicked to have more than 1 column?

a sample would help explain what you mean

Im using one now. It has two columns, its no problem.
Do you want some rows NOT to have multi columns, and some do?

I’ve had that working since RB 4.5 


How are you populating the rows?

The code in the listbox open event:

[code]
Dim i As Integer
Dim j As Integer
dim itables As Integer
dim iColumns As Integer
dim iRows As Integer
dim sSQL As String
dim sTableName As String
dim sColumnName As String
dim rsTempTables As RecordSet
dim rsTempColumns As RecordSet
dim rsTemp As RecordSet
dim bFirstAdd As Boolean
dim sColumns As String

	sSQL = "SELECT TableName FROM dbTables"
	rsTempTables = dbSQL.SQLSelect(sSQL)
	itables = rsTempTables.RecordCount
	rsTempTables.MoveFirst
	
	i = 1
	rsTempTables.MoveFirst
	while not rsTempTables.eof
			sTableName = rsTempTables.Field("TableName").StringValue
			sSQL       = "SELECT * FROM '" + sTableName + "'"
			rsTemp     = dbSQL.SQLSelect(sSQL)
			iRows      = rsTemp.RecordCount
			Me.AddFolder ""
			me.Cell(i-1,0) = sTableName
			//me.Cell(i-1,2) = str(iRows)
			sSQL          = "SELECT ColumnName FROM dbColumns WHERE TableName = '" + sTableName + "'"
			rsTempColumns = dbSQL.SQLSelect(sSQL)
			iColumns = rsTempColumns.RecordCount
			rsTempColumns.MoveFirst
			j = 1
			bFirstAdd = True
			while not rsTempColumns.EOF
					sColumnName  = rsTempColumns.Field("ColumnName").StringValue
					if bFirstAdd then
							sColumns = sColumnName
							bFirstAdd = False
					else
							sColumns = sColumns + "," + sColumnName
					end if
					rsTempColumns.MoveNext
			wend
			me.Cell(i-1,1) = sColumns
			i = i + 1
			rsTempTables.MoveNext
	Wend
	[/code]

The code in the ExpandRow Event:

[code] Dim sTables as String
Dim i as Integer
dim j As Integer

	sTables = Me.Cell(row,1)
	j       = CountFields(sTables,",")
	For i = 1 to j
			  Me.AddRow ""
			  Me.Cell(Me.LastIndex,0)=NthField(sTables,",",i)
	Next
	[/code]

The upper group are the tables in the database.
The sub-groups that display when the table disclosure triangle is clicked are the columns in the selected table.
I would like to add 2 extra columns that contain data ONLY on the Tables. The 1st would be the number of records in the table and the second would be the number of columns in the table. There would be no other columns for the Columns when displayed.

Does this explain what I need better.

You need a much more robust data structure than just a comma delimited string. Create some classes to store in RowTag. Or better, just go back to the database when a row is expanded an fetch whatever info you need.

Btw, your initial issue is due to the fact that you’re storing the data for the table in Cell(row,1). Don’t do that.

Tim, like I said, I mostly copied the code from the example in the ListBox documentation. It had both sets of data as delimited strings but I changed the Tables (top level) to reading the Database. then just loaded the columns for each table into a string.

Tag the ‘table’ rows in some way (rowtag, celltag)
Put into that what the extra information should say

Then draw the extra information to the row graphic in the CelltextPaint event

That way, all rows have only one column, but you are adding extra info that resembles extra columns

Its also how you get images into a row.

@william plunkett - what exactly are you trying to achieve here?

  • Are you trying to create rows in the ListBox containing the fields for each of those table columns?
  • Should the actual datatable columns be the header for the expanded subsection with the matching field contents shown below?
  • Or is this just o display the schema for the tables when expanded?

For a deeper look into the magic of the ListBox, have you watched Paul’s excellent webinars?
https://youtu.be/1o39SA5sA8o
https://youtu.be/Y8UKHYO-T4Y

Hierarchical listbox really highlights the need to separate presentation from the backing storage. The data you put into a hierarchical listbox is ephemeral. The rows are actively destroyed when you collapse them. Therefore it is imperative that you store your data elsewhere and use the listbox purely for display. The examples in the documentation are child’s playthings and serve only to illustrate the concept rather than do anything useful in the real world.

The key concept is that the parent row must contain enough identifying information (record ID, table name, etc) to be able to create the child rows on demand. RowTag is the perfect place to store this, even if you are also displaying some of it in a cell.

@Jeff Tullin what is the advantage of drawing the cells rather than simply loading them in ExpandRow? It seems overly complicated.

1 Like

In the picture, the OP seems to be asking for rows which are Table names, to have several columns
The extra columns contain and

So The ImageMaster row might say ImageMaster | 63 | 23

If the listbox is given 3 columns, all the expanded children ( the column names) get 3 columns too, and that would seem not to be required.

So making the name of the ImageMaster row actually become " ImageMaster | 63 | 23" is one way to do fake it.
Another is to add detail like record count and maybe gfx in the cell text paint.
That gives better control over lining up the fake columns as they can be drawn relative to the right of the list, rather than the left, allowing for numeric justification without the need for a column

Has anyone some help for this topic? Other than “I’m using one now” I don’t see any actual answer to the original question.

Does it in fact have to be “faked” or is there an actual way/method for getting a folder to have more than one column?

Much like Bill I want a folder that will show some subtotals of items in its child rows in columns that will match the child rows’ column data.

Take a look at my reply to another thread about the same topic for a simple example:

https://forum.xojo.com/45778-multicolumn-hierarchical-listbox

You mean like this? This is not faked, it is a hierarchical list box with 3 columns (only two visible here):

[quote=373784:@Jared Feder]Take a look at my reply to another thread about the same topic for a simple example:

https://forum.xojo.com/45778-multicolumn-hierarchical-listbox[/quote]

Thank you, that is exactly what I needed to see. Much appreciated

BTW - there is a Feedback request in to add allowing an array to generate the cells of a folder like they do a normal row:
<https://xojo.com/issue/50671>