cancel
Showing results for 
Search instead for 
Did you mean: 

how to write a recursive function to create a treeview from data in datawindow?

Former Member
0 Kudos

I have a parent-child data in a datawindow from a table mytab(id, pid....)

Then I want to use to data to create a tree in treeview.

I try to use recursive function, but have problem with datawindow as I use filter to change the data in datawindow.

here is my code:

    of_addnode(treeviewitem node, rootrow):

   

    int li_rows,li_newitem, i

    treeviewitem li_tvitem

   

    dw_1.SetFilter("pid = " + string(node.data))

    dw_1.Filter( )

   

    li_rows =  dw_1.RowCount()

   

    if li_rows = 0 then

    return

    end if

   

    for i = 1 to li_rows

    li_tvitem.level = node.level +1

    li_tvitem.data = dw_1.GetItemNumber(i,"id")

    li_tvitem.label = dw_1.GetItemString(i,"description")

    li_tvitem.pictureindex = 1

    li_tvitem.selectedpictureindex = 2

    li_newitem = tv_1.insertitemsort (rootrow, li_tvitem)  // insert a new node

    of_addnode(li_tvitem,li_newitem)

  

    dw_1.SetFilter("pid = " + string(node.data))  //restore data back to filter, problem here. tree will have duplicate item

            dw_1.Filter( )

    next

how to create a recursive function from one datasource datawindow for this case?

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Try using a datastore, see below. I haven't tested that but I think that should work.

of_addnode(treeviewitem node, rootrow):

    int li_rows,li_newitem, i

    treeviewitem li_tvitem

   datastore lds_1

    dw_1.SetFilter("pid = " + string(node.data))

    dw_1.Filter( )

   lds_1    = Create DataStore

   lds_1.DataObject = dw_1.DataObject

   lds_1.ImportString(dw_1.describe("datawindow.data"))

    li_rows =  lds_1.RowCount()

    if li_rows = 0 then

    return

    end if

    for i = 1 to li_rows

    li_tvitem.level = node.level +1

    li_tvitem.data = lds_1.GetItemNumber(i,"id")

    li_tvitem.label = lds_1.GetItemString(i,"description")

    li_tvitem.pictureindex = 1

    li_tvitem.selectedpictureindex = 2

    li_newitem = tv_1.insertitemsort (rootrow, li_tvitem)  // insert a new node

    of_addnode(li_tvitem,li_newitem)

 

I'm not sure if you would need this filter here... maybe to clear out the filter you need to specify empty string...

as dw_1.SetFilter('')

    dw_1.SetFilter("pid = " + string(node.data))  //restore data back to filter, problem here. tree will have duplicate item

            dw_1.Filter( )

    next

destroy lds_1

Answers (3)

Answers (3)

Former Member
0 Kudos

You really should have a different datastore for each level, retrieve it in the itempopulate event and add the treeview items there. It will be much faster because only the nodes you are actually looking at are retrieved & created.

Former Member
0 Kudos

thanks for help, guys. I use datastore for each level and resolve the problem.

Former Member
0 Kudos

Hi,

You have 2 problems here :

1- You are using a single table with columns "id" and "parent_id". For example in the table

employee in EASdemodb, you have emp_id and manager_id.

The problem is how you set the manager_id for the Top Managers. In the table employee,

there are 2 Top managers and the emp_id is the same than the manager_id for these employees.

So in you filter, you have to add for sub-level nodes a CLAUSE :

AND  employee_manager_id <> employee_emp_id

2-the second problem is when you change the filter for sub_levels and then get back

to the parent and set the parent filter, you are not guaranteed that the Rows order is the same

as before.

So when you call GetItemNumber, you may have a different row value.

This is why you get duplication labels in your treeview.

The solution is to set a Sort order to the datawindow :

ids_employees.SetFilter(ls_current_filter)

ids_employees.Filter( )

ids_employees.setsort("employee_emp_id")

ids_employees.Sort()

See below my function of_populate (treeviewitem atvi_item, long ll_parent)

For the first call , set ll_parent = 0

Hope this Helps.

Abdallah.

//-------------------------------------------------------------------------


int li_rows, li_newitem, li, li_level
treeviewitem ltvi_tem
string ls_parent_filter, ls_current_filter
if isValid (atvi_item) AND ll_parent > 0 Then
ls_parent_filter = ids_employees.Describe("DataWindow.Table.Filter")
ls_current_filter = "employee_manager_id = " + string(atvi_item.data) + " AND  employee_manager_id <> employee_emp_id"
ltvi_tem.level = atvi_item.level + 1
ELSE
ls_parent_filter = "employee_manager_id = employee_emp_id"
ls_current_filter = "employee_manager_id = employee_emp_id"
li_level = 0
END IF

ids_employees.SetFilter(ls_current_filter)
ids_employees.Filter( )
ids_employees.setsort("employee_emp_id")
ids_employees.Sort()

li_rows =  ids_employees.RowCount()

for li = 1  TO  li_rows
ltvi_tem.level = li_level
ltvi_tem.data = ids_employees.GetItemNumber (li, "employee_emp_id")
ltvi_tem.label = ids_employees.GetItemString (li, "employee_emp_fname") + " " + ids_employees.GetItemString (li, "employee_emp_lname")
ltvi_tem.pictureindex = 1
ltvi_tem.selectedpictureindex = 2
li_newitem = tv_1.insertitemsort (ll_parent, ltvi_tem)  // insert a new node
of_populate (ltvi_tem, li_newitem)
next
ids_employees.SetFilter(ls_parent_filter) 
ids_employees.Filter( )
return 1

Former Member
0 Kudos

If you must use code like this, filtering the datawindow or datastore whilst trying to read from it as you are is just going to create pain.


Why not use the query from your existing datawindow as the datasource for a treeview datawindow? If your front end can't access the database then get the data from a datastore and load it into the treeview datawindow (as you're already trying to do).

Former Member
0 Kudos

Sorry,  "as you're trying to do" should have been "as Neil suggested";  but you would preferably use dw_1.object.data.primary instead of importstring().