wxListCtrl and ClientData

BlitzMax Forums/Brucey's Modules/wxListCtrl and ClientData

Glenn Dodd(Posted 2008) [#1]
Here is a stripped down version of a program i am working on.
There is a GUI file and a Main file.

The main file creates a sqllite database and adds some tables and data.

The first table (MainTask) is read by TMainTask and a list is returned to the frame to be populated in the topmost ListCtrl (and stored as ClientData). I have a listbox example that works fine but the difference is the first item in the listbox is the primary key i need for the next lookup.

I am displaying the data in a different order to what is in the table. The table has a Primary Key of MainTaskID but this is not in the first column. This might be my problem and if so i guess i can use it in column 1 but give it a zero width.

Once i click one of these items in the ListCtrl it is supposed to pass the correct MainTaskID to the TSubTask.GetListForTypeId function so the relevant Sub Tasks can be returned and displayed in the second ListCtrl.

Unfortunately only the MainTaskID = 1 SubTask is returned and displayed.

I haven't got the hang of this client data for the listctrl yet.

The code looks quite messy but this is because i normally have 3 sets of files: GUI, DataBase Types and the Main File.
That is why i am passing values around so much.

Any help appreciated.

Cheers
Glenn

ListCtrlClientDataGUI.bmx


MainFile



Brucey(Posted 2008) [#2]
You shouldn't be casting away your wxListEvent object in the ListCtrl1Clicked() method.

Try using event.GetIndex() instead.

:-)

Also be very aware that currently wxListCtrls do not reference count any object you set in the item client data, so you'll need to keep a separate list around in order to prevent any objects added into the wxListCtrl from being GC'd.

This will be sorted in the future some time... just not had time to go over it yet.


Glenn Dodd(Posted 2008) [#3]
not really sure what you mean in the first 2 sentences.
There are only 2 lines it could refer to and i tried event.GetIndex() but then it won't compile.


Brucey(Posted 2008) [#4]
change :
Method ListCtrl1Clicked(event:wxListEvent)

	Local index:Int = wxCommandEvent(event).GetInt()

to
Method ListCtrl1Clicked(event:wxListEvent)

	Local index:Int = event.GetIndex()



Glenn Dodd(Posted 2008) [#5]
ah
i left the wxCOmmandEvent in.


Brucey(Posted 2008) [#6]
ah :-)


Glenn Dodd(Posted 2008) [#7]
when i click the first Main Task i get the correct Sub Task.
the index is 0. does this refer column0?
when i click the second main task i get a null reference from:
Local sMainTask:TMainTask = TMainTask(m_listCtrl1.GetItemData(index))
index is 1

i don't think it has been GC'ed as it finds data for the first item, but i could be wrong


Glenn Dodd(Posted 2008) [#8]
scratch that.
if i click the either item for the first time it works correctly. then click the other item and it fails, so i guess gc has occured.

so to keep the list around can i add a field to the type and use that instead?


Brucey(Posted 2008) [#9]
Yeah, you could have a field representing the currently selected item.

You could also, when building the second list, populate those items into a list contained within your TMainTask type. Logically, a TMainTask can contain a list of TSubTasks.


Glenn Dodd(Posted 2008) [#10]
So i think you mean add this line to the TMainTask.GetListForTypeId function:
' added this line to get the SubTasks associated to each MainTask, and added a list object to the MainTaskList
Local STList:TList = TSubTask.GetListForTypeId(MainTask.MainTaskID)

then when i am adding the ClientData in MyFrame2.MTInsertIntoList() with item.SetData(dataSet) then i should also have my SubTask List, specific for that MainTask entry (MainTaskID).

Next i click on a MainTask and it does a For Eachin loop to get the SubTask Data from the ClientData.

It sounds reasonable to me, but i haven't the faintest idea how to access the second list in the client data. As you can see i have made no attempt to modify the Populate_m_listCtrl2 or STInsertIntoList methods.

Well i did make some attempts but they failed miserably...

I haven't added the list field either yet, to prevent the client data being GC'ed. I can't seem to wrap my head around adding a list with lists inside it, and then accessing that data afterwards... it is the data access i am struggling with the most.

i feel like this is one of the last hurdles to cross. in my main program using menus and popup windows with a right click is working in a seperate sample program, adding/editing/deleting records is easy and updating the GUI just recalls some of these functions.

I think i am close to pulling the disparate functionality together into the main program to finally get the Task List Manager done.

I just need some help with this part again.

Regards
Glenn




Glenn Dodd(Posted 2008) [#11]
After rereading everything i can find about Client Data I can confidently say i understand it conceptually.
Accessing its data in a clean way that makes sense to me is another story.
So because this has delayed any progress on my actual project for the last week i have decided to not use client data and go back to the simple method of putting the primary key into the first ListCtrl column and giving it a width of 0. That way it is not seen but i can access it with wxListItem.GetText().

Not the most elegant solution but since i am still a beginner, hey it works :)

If anyone wants to see what i ended up with just let me know and i will post the commented code.

Cheers
Glenn


Brucey(Posted 2008) [#12]
Righty... I've added support for reference counting Objects stored in wxListCtrl item client data now.

From my initial tests :
1) Added objects to items, and see how long they stay valid for
2) DeleteallItems and replace, seeing if we are leaking.

both are passing, so I'm reasonably happy that it's working now.
However, it will require normal use to make sure I haven't missed anything out.

This means that you should be able now to safely use data stored in client data without having to keep your own copy of it elsewhere.


Glenn Dodd(Posted 2008) [#13]
Have we praised you enough lately?

Many thanks again.

Glenn


René(Posted 2009) [#14]
Hi Brucey,

I created a smal ListCtrl test like Glenn did.
The aim is to bind custom user data (in this case a TData test object) to a ListItem object.

In the example there is a ListCtrl and a Button. Click the button and a new TData object with a corresponding ListItem gets created. Now this works fine. Everytiem I press the button a new TData object gets created ...0,1,2,3,4,5,6,... and so on.

On line 160: when I uncomment the line to add my TData object as custom data with SetData() command, something goes wrong. When I click the button several times it seems that previous TData object gets overwritten instead of creating a new one ...0,1,4,3,4,...

Do you have an idea whats going wrong?

Thank You
René