Hierarchical ListBox with database data returned

I’m trying to make a hierarchical ListBox with database data returned.
For example, there is only one parent row and it can have several child. The each row has 10 columns.
With the value of INSTANCE, if it is 0 then it shows parent, otherwise it would be individual child(INSTANCE=1 OR INSTANCE=2 …)

For some reason, I need to have one hidden column(dataList.Heading(0) = “D”)

By using the first column(+ sign), if I click the column, then the child rows should get collapsed, and of course if I click it again, it should get disappeared like Hierarchical Listbox.

Below is my test code, but as you know it doesn’t work. -.-
I would like to get any comment for implemeting this feature.
Please help me out.

-- In populateListbox method

  If rs Is Nil Then Return
  
  // set up listbox state for population
  dataList.DeleteAllRows
  
  dataList.ColumnCount = rs.FieldCount + 1
  dataList.Heading(0) = "D"
  dataList.Column(0).WidthExpression="0"
  dataList.Heading(1) = "H"
  dataList.Column(1).WidthExpression="50"
  
  For i As Integer = 2 To dataList.ColumnCount - 1
    dataList.Heading(i) = rs.IdxField(i-1).Name
  Next
  
  
  While Not rs.EOF
    
    
    If rs.IdxField(2).StringValue <> "0" then  'If Child
      dataList.AddFolder ""
      
      For i As Integer = 1 To dataList.ColumnCount - 1
        dataList.Cell(dataList.LastIndex, i) = rs.IdxField(i).StringValue
      Next
	  
    Else
      
      For i As Integer = 1 To dataList.ColumnCount - 1
        dataList.Cell(dataList.LastIndex, i) = rs.IdxField(i).StringValue
      Next
      
      
    End if
    
    rs.MoveNext
  Wend
  
  Datalist.Refresh

[quote=198449:@changwon lee] If rs.IdxField(2).StringValue <> "0" then 'If Child dataList.AddFolder ""
[/quote]
First, the logic here is backward. You use AddFolder to add the header row, not the child row. Use AddRow for child rows.

Second, with a hierarchical listbox, it is up to you to “remember” the child rows for each header, so you can recreate them when the header is expanded. The listbox itself does not remember them after a row is collapsed. It simply discards that information. It’s up to you to store it some place where you can retrieve it again.

I am trying a similar thing. I’d like to display the content of a database in a multilevel hierarchical listbox. All lines, folders and rows are coming from the same table. In the database I defined a column “parentfolder”, where the unique id of the parent folder is stored. There is a boolean field “isfolder” to store, whether the line is a folder or a row. The folders of the first level I identify by the “parentfolder”-value of 0.

My first problem is, that I just can’t the expand command to work. The subitems under the first level of folders are not displaying correctly. this is how I go about in the open event:

rs = db.SQLSelect("select * from "+dbTableName+" where parentfolder is '0' ")
      foundCounter = 0
      for rowCounter = 0 to rs.RecordCount-1 
        
        'me.insertFolder(foundCounter,rs.Field("id")) 
        me.AddFolder(rs.Field("id")) 
        
        for columnCounter = 0 to me.columnCount-1 
          for i as integer = 0 to rs.fieldCount-1 //Ubound(columnOrderArray) 
            if me.ColumnTag(columnCounter) = rs.IdxField(i+1).name then 
              me.Cell(foundCounter,columnCounter) = rs.Field(me.ColumnTag(columnCounter)) 
            end if
          next
        next
        
        dim id as string = rs.Field("id")
        me.rowTag(foundCounter) = id
        me.CellTag(foundCounter,1) = rs.Field("parentfolder") 
        
        'me.Expanded(foundCounter) = true // expand folder doesn't work, need to open manually

        foundCounter = foundCounter+1
        rs.MoveNext
      next

Then in the expandRow event:

rs = db.SQLSelect("select * from "+dbTableName+" where parentfolder is "+thisFolderID) 
  
  for rowCounter = 0 to rs.RecordCount-1 
    
    dim parentfolder as string = rs.Field("parentfolder")
    dim isfolder as boolean = rs.Field("isfolder")
    if isfolder = true  then 
      me.insertFolder(row+rowCounter+1,"Folder") 
      'me.Expanded(foundRowCounter) = true // expand folder not working yet
    else 
      me.insertRow(row+rowCounter+1,"Row")
    end if
    
    me.columnCount = columnOrderArray.Ubound+1 
    for columnCounter = 0 to me.columnCount-1 
      
      for i as integer = 0 to rs.fieldCount-1 
        if me.ColumnTag(columnCounter) = rs.IdxField(i+1).name then 
          me.Cell(rowCounter+row+1,columnCounter) = rs.Field(me.ColumnTag(columnCounter)) 
        end if
      next
    next
    
    dim id as string = rs.Field("id")
    me.RowTag(rowCounter+row+1) = id 
    parentFolder = rs.Field("parentfolder")
    me.CellTag(rowCounter+row+1,1) = parentFolder
    
    rs.MoveNext
    
  next

Any idea, why it should not work properly?

My second problem is, that in the folders there should be a sum of a row in the subitems. It means, the values of the chilren of a row should still be stored in the folder-row, when it is collapsed. I don’t know how to store it there. Best would be in a recordset? how am I going to do this?

In your open code, you’re using foundcounter, but never actually setting it.
You’re setting the Cell() value to rs.Field(me.ColumnTag(columnCounter)). That should probably be rs.Field(me.ColumnTag(columnCounter)) .StringValue. (It should throw a compile error.)

In your Expand code, you’re doing way too much work. Just use AddFolder and AddRow. They will be put in the correct place.

Thanks Tim. I forgot to mention it. In my code, I use foundCounter = foundCounter+1 right before the last next command. I now found inspiration in this payed tutorial: http://great-white-software.com/rblibrary/index.php?main_page=product_info&cPath=15&products_id=64. The trick is, to store the children in a class, that can be appended to itself. The class is then written in to a CellTag.