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
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
' ' BlitzMax code generated with wxCodeGen v1.02 : 10 Mar 2008 22:34:08 ' ' ' PLEASE DO "NOT" EDIT THIS FILE! ' SuperStrict Import wx.wxFrame Import wx.wxListCtrl Import wx.wxPanel Import wx.wxWindow Type MyFrame2Base Extends wxFrame Field m_panel5:wxPanel Field m_listCtrl1:wxListCtrl Field m_listCtrl2:wxListCtrl Method Create:MyFrame2Base(parent:wxWindow = Null,id:Int = wxID_ANY, title:String = "", x:Int = -1, y:Int = -1, w:Int = 787, h:Int = 328, style:Int = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL) Return MyFrame2Base(Super.Create(parent, id, title, x, y, w, h, style)) End Method Method OnInit() Local bSizer11:wxBoxSizer bSizer11 = New wxBoxSizer.Create(wxVERTICAL) m_panel5 = New wxPanel.Create(Self, wxID_ANY,,,,, wxTAB_TRAVERSAL) Local bSizer12:wxBoxSizer bSizer12 = New wxBoxSizer.Create(wxVERTICAL) m_listCtrl1 = New wxListCtrl.Create(m_panel5, wxID_ANY,,,,, wxLC_REPORT) m_listCtrl1.SetMinSize(700,-1) bSizer12.Add(m_listCtrl1, 1, wxALL, 5) m_listCtrl2 = New wxListCtrl.Create(m_panel5, wxID_ANY,,,,, wxLC_REPORT) m_listCtrl2.SetMinSize(700,-1) bSizer12.Add(m_listCtrl2, 1, wxALL, 5) m_panel5.SetSizer(bSizer12) m_panel5.Layout() bSizer11.Add(m_panel5, 1, wxEXPAND | wxALL, 5) SetSizer(bSizer11) Layout() m_listCtrl1.ConnectAny(wxEVT_COMMAND_LIST_ITEM_SELECTED, _ListCtrl1Clicked, Null, Self) End Method Function _ListCtrl1Clicked(event:wxEvent) MyFrame2Base(event.sink).ListCtrl1Clicked(wxListEvent(event)) End Function Method ListCtrl1Clicked(event:wxListEvent) DebugLog "Please override MyFrame2.ListCtrl1Clicked()" event.Skip() End Method End Type
MainFile
' ' Example application stub generated by wxCodeGen v1.02 : 10 Mar 2008 21:41:30 ' SuperStrict Framework wx.wxApp Import "ListCtrlClientDataGUI.bmx" Import BaH.DBSQLite Import brl.filesystem Import brl.system Const cListCtrlDateWidth:Int = 80 New MyApp.run() Type MyApp Extends wxApp Field frame:MyFrame2 Method OnInit:Int() ?macos ' make the default Mac font for controls not so big wxSystemOptions.SetOption(wxWINDOW_DEFAULT_VARIANT, wxWINDOW_VARIANT_SMALL) ? ' needed so my graphics show up wxInitAllImageHandlers() ' for Mac/Win32 (it is default on Linux) wxImage.AddHandler( New wxXPMHandler ) ' create the frame Local frame:MyFrame2 = MyFrame2(New MyFrame2.Create(, , "ListCtrl Client Data Test")) ' frames are created hidden. You need to manually show it. frame.show() ' make sure it is brought to the front SetTopWindow(frame) Return True End Method End Type Type MyFrame2 Extends MyFrame2Base Method OnInit() Super.OnInit() ' There are 2 list controls. Create the Column Headers here CreateListCtrlColumnHeaders() ' populate the Due Date ListCtrl PopulateListCtrl(m_listCtrl1) End Method Method CreateListCtrlColumnHeaders() ' do the First List Control SetColumnHeadings(m_listCtrl1) ' do the Second List Control SetColumnHeadings(m_listCtrl2) End Method Method SetColumnHeadings(ListControl:wxListCtrl) Select ListControl Case m_listCtrl1 ListControl.InsertColumn(0, ("TM"), wxLIST_FORMAT_LEFT, 30) ' Team Member Initials ListControl.InsertColumn(1, ("Created"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth) ListControl.InsertColumn(2, ("Due Date"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth) ListControl.InsertColumn(3, ("Completed"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth) ListControl.InsertColumn(4, ("Cancelled"), wxLIST_FORMAT_CENTRE, cListCtrlDateWidth) ListControl.InsertColumn(5, ("Main Task Name"), wxLIST_FORMAT_LEFT,200) Case m_listCtrl2 ListControl.InsertColumn(0, ("TM"), wxLIST_FORMAT_LEFT, 30) ' Team Member Initials ListControl.InsertColumn(1, ("Created"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth) ListControl.InsertColumn(2, ("Due Date"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth) ListControl.InsertColumn(3, ("Completed"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth) ListControl.InsertColumn(4, ("Cancelled"), wxLIST_FORMAT_CENTRE, cListCtrlDateWidth) ListControl.InsertColumn(5, ("Sub Task Name"), wxLIST_FORMAT_LEFT,200) Default DebugLog "You have passed a ListCtrl that doesn't exist" End Select End Method Method PopulateListCtrl(ListControl:wxListCtrl) ' delete the Items, so the column headers don't need to be recreated ListControl.DeleteAllItems() ' check the ListCtrl exists If ListControl Then ' Get the data for the MainTask ListCtrl (using the id) from TSelector Local list:TList = TMainTask.GetListForTypeId() ' i is the row number in the ListCtrl Local i:Int = 0 For Local dataset:TMainTask = EachIn list ' InsertIntoList(Row Number, the data for this element of the list, the name of the ListCtrl) MTInsertIntoList(i, dataset, ListControl) ' Increment i so you are always adding to the end of the ListCtrl ' comment this line out if you want your listctrl populated in reverse, ie i = 0 i:+ 1 Next End If End Method Method MTInsertIntoList(index:Int, dataSet:TMainTask, list:wxListCtrl) ' wxListItem - This type stores information about a wxListCtrl item or column. ' Some comments taken from <a href="http://www.gibbongames.com/content/view/52/50/" target="_blank">http://www.gibbongames.com/content/view/52/50/</a> ' wxListItem encapsulates the contents of a given listbox cell. ' So each row/column combination has its own wxListItem structure. Local item:wxListItem = New wxListItem.Create() ' Define all the parameters for the column, then use list.SetItem(item) to bind it ' Column 0 item.SetImage(-1) item.SetText(dataSet.TMID) item.SetId(index) '******************* set the Client Data???? so it can be used in "Method MainTaskSelected(event:wxListEvent)" item.SetData(dataSet) ' Apparently Column 0 requires InsertItem, but Column n > 0 requires SetItem (assuming that Column 0 has been previously inserted). list.InsertItem(item) ' Column 1 item.SetText(dataSet.MTCreateDate) item.SetColumn(1) list.SetItem(item) ' Column 2 item.SetText(dataSet.MTDueDate) item.SetColumn(2) list.SetItem(item) ' Column 3 item.SetText(dataSet.MTCompletedDate) item.SetColumn(3) list.SetItem(item) ' Column 4 If dataSet.MTCancelled = 1 Then item.SetText("Yes") Else item.SetText("No") End If item.SetColumn(4) list.SetItem(item) ' Column 5 item.SetText(dataSet.MTName) item.SetColumn(5) list.SetItem(item) End Method Method ListCtrl1Clicked(event:wxListEvent) DebugLog "ListCtrl1Clicked" ' once the MainTask ListCtrl is clicked we need to populate the SubTask ListCtrl ' Find the index of the item clicked Local index:Int = wxCommandEvent(event).GetInt() ' Get the value of the item clicked ' Note: This is the TMainTask object we stored earlier. ' It gives us access to the Id, for example, which gives us a quicker ' lookup in the SQL. (ie. no table joins, since the Id is a foreign key!) ' ***************************** GetItemData(index) looks correct but i keep getting a 1 sent to the PopulateSubTask as the id Local sMainTask:TMainTask = TMainTask(m_listCtrl1.GetItemData(index)) ' now fill in the SubTask ListCtrl Populate_m_listCtrl2(sMainTask.MainTaskID, m_listCtrl2) End Method Method Populate_m_listCtrl2(id:Int, ListControl:wxListCtrl) ' delete the Items, so the column headers don't need to be recreated ListControl.DeleteAllItems() ' check the ListCtrl exists If ListControl Then ' Get the data for the MainTask ListCtrl (using the id) from TSelector Local list:TList = TSubTask.GetListForTypeId(id) ' i is the row number in the ListCtrl Local i:Int = 0 For Local dataset:TSubTask = EachIn list ' InsertIntoList(Row Number, the data for this element of the list, the name of the ListCtrl) STInsertIntoList(i, dataset, ListControl) ' Increment i so you are always adding to the end of the ListCtrl ' comment this line out if you want your listctrl populated in reverse, ie i = 0 i:+ 1 Next End If End Method Method STInsertIntoList(index:Int, dataSet:TSubTask, list:wxListCtrl) ' wxListItem - This type stores information about a wxListCtrl item or column. ' Some comments taken from <a href="http://www.gibbongames.com/content/view/52/50/" target="_blank">http://www.gibbongames.com/content/view/52/50/</a> ' wxListItem encapsulates the contents of a given listbox cell. ' So each row/column combination has its own wxListItem structure. Local item:wxListItem = New wxListItem.Create() ' Define all the parameters for the column, then use list.SetItem(item) to bind it ' Column 0 item.SetImage(-1) item.SetText(dataSet.TMID) item.SetId(index) '******************* set the Client Data???? so it can be used in "Method MainTaskSelected(event:wxListEvent)" item.SetData(dataSet) ' Apparently Column 0 requires InsertItem, but Column n > 0 requires SetItem (assuming that Column 0 has been previously inserted). list.InsertItem(item) ' Column 1 item.SetText(dataSet.STCreateDate) item.SetColumn(1) list.SetItem(item) ' Column 2 item.SetText(dataSet.STDueDate) item.SetColumn(2) list.SetItem(item) ' Column 3 item.SetText(dataSet.STCompletedDate) item.SetColumn(3) list.SetItem(item) ' Column 4 If dataSet.STCancelled = 1 Then item.SetText("Yes") Else item.SetText("No") End If item.SetColumn(4) list.SetItem(item) ' Column 5 item.SetText(dataSet.STName) item.SetColumn(5) list.SetItem(item) End Method End Type Type TDatabaseTables Global db:TDBConnection Method Init:TDatabaseTables() If Not db Then DeleteFile("ListCtrlClientData.db") DebugLog "Deleted File to start with a fresh one" If Not FileType("ListCtrlClientData.db") Then CreateDB("ListCtrlClientData.db") End If db = LoadDatabase("SQLITE", "ListCtrlClientData.db") End If ' Check that the DB connection has been made If Not db Then Notify("Unable to Open the Database ListCtrlClientData.db") End End If ' Check if the database has an error on opening If db.hasError() Then errorAndClose(db) End If Return Self End Method Method CreateDB(filename:String) Local dbase:TDBConnection = LoadDatabase("SQLITE", "ListCtrlClientData.db") Local s:String ' Create tblMainTask s = "CREATE TABLE tblMainTask (MainTaskID integer primary key AUTOINCREMENT, " + .. " MTName varchar(100), " + .. " MTCreateDate varchar(10), " + .. " MTDueDate varchar(10), " + .. " MTCompletedDate varchar(10), " + .. " MTCancelled integer, " + .. " SelectorID integer, " + .. " TMID integer) " dbase.executeQuery(s) If dbase.hasError() Then errorAndClose(dbase) End If DebugLog "tblMainTask Created" ' Create tblSubTask s = "CREATE TABLE tblSubTask (SubTaskID integer primary key AUTOINCREMENT, " + .. " STName varchar(100), " + .. " STOrder integer, " + .. " STMemo varchar(1000), " + .. " STCreateDate varchar(10), " + .. " STDueDate varchar(10), " + .. " STCompletedDate varchar(10), " + .. " STLastUpdatedDate varchar(10), " + .. " STCancelled integer, " + .. " MainTaskID integer, " + .. " TMID integer) " dbase.executeQuery(s) If dbase.hasError() Then errorAndClose(dbase) End If DebugLog "tblSubTask Created" ' create some data... ' tblMainTask dbase.executeQuery("INSERT INTO tblMainTask values (NULL, 'MainTask One', '01 Jan 2008', '02 Feb 2008', '03 Mar 2008', 0, 1, 1)") dbase.executeQuery("INSERT INTO tblMainTask values (NULL, 'MainTask Two', '01 Mar 2008', '02 Feb 2008', '03 Jan 2008', 0, 1, 2)") ' tblSubTask dbase.executeQuery("INSERT INTO tblSubTask values (NULL, 'SubTask One for MainTask One', 1, 'Memo Field','01 Jan 2008', '02 Feb 2008', '03 Mar 2008', '04 Mar 2008', 0, 1, 1)") dbase.executeQuery("INSERT INTO tblSubTask values (NULL, 'SubTask One for MainTask Two', 1, 'Memo Field','01 Jan 2007', '02 Feb 2007', '03 Mar 2007', '04 Mar 2007', 0, 2, 2)") dbase.executeQuery("INSERT INTO tblSubTask values (NULL, 'SubTask Two for MainTask Two', 1, 'Memo Field','02 Jan 2007', '03 Feb 2007', '04 Mar 2007', '05 Mar 2007', 0, 2, 2)") dbase.close() End Method Function errorAndClose(db:TDBConnection) DebugLog(db.error().toString()) db.close() End End Function End Type Type TMainTask Extends TDatabaseTables Field MainTaskID:Int Field MTName:String Field MTCreateDate:String Field MTDueDate:String Field MTCompletedDate:String Field MTCancelled:Int Field SelectorID:Int Field TMID:Int Method Init:TMainTask() Return TMainTask(Super.init()) End Method Function GetListForTypeId:TList() Local list:TList = New TList Local mt:TMainTask = New TMainTask.Init() If db.isOpen() Then Local sql:String = "SELECT MainTaskID, MTName, MTCreateDate, MTDueDate, MTCompletedDate, MTCancelled, SelectorID, TMID " sql = sql + "FROM tblMainTask " ' Get the data from the table Local query:TDatabaseQuery = db.executeQuery(sql) ' Loop through each record and add the values to the TList For Local record:TQueryRecord = EachIn query Local MainTask:TMainTask = New TMainTask MainTask.MainTaskID = record.GetInt(0) MainTask.MTName = record.GetString(1) MainTask.MTCreateDate = record.GetString(2) MainTask.MTDueDate = record.GetString(3) MainTask.MTCompletedDate = record.GetString(4) MainTask.MTCancelled = record.GetInt(5) MainTask.SelectorID = record.GetInt(6) MainTask.TMID = record.GetInt(7) DebugLog "Start of Data for MainTask record" DebugLog "MainTaskID = " + MainTask.MainTaskID DebugLog "MTName = " + MainTask.MTName DebugLog "MTCreateDate = " + MainTask.MTCreateDate DebugLog "MTDueDate = " + MainTask.MTDueDate DebugLog "MTCompletedDate = " + MainTask.MTCompletedDate DebugLog "MTCancelled = " + MainTask.MTCancelled DebugLog "SelectorID = " + MainTask.SelectorID DebugLog "TMID = " + MainTask.TMID DebugLog "End of Data for MainTask record" list.AddLast(MainTask) Next EndIf Return list End Function End Type Type TSubTask Extends TDatabaseTables Field SubTaskID:Int Field STName:String Field STOrder:Int Field STMemo:String Field STCreateDate:String Field STDueDate:String Field STCompletedDate:String Field STLastUpdatedDate:String Field STCancelled:Int Field MainTaskID:Int Field TMID:Int Method Init:TSubTask() Return TSubTask(Super.init()) End Method Function GetListForTypeId:TList(id:Int) Local list:TList = New TList Local st:TSubTask = New TSubTask.Init() If db.isOpen() Then Local sql:String = "SELECT SubTaskID, STName, STOrder, STMemo, STCreateDate, STDueDate, STCompletedDate, STLastUpdatedDate, STCancelled, MainTaskID, TMID " sql = sql + "FROM tblSubTask " sql = sql + "WHERE MainTaskID = " + id ' Get the data from the table Local query:TDatabaseQuery = db.executeQuery(sql) ' Loop through each record and add the values to the TList For Local record:TQueryRecord = EachIn query Local SubTask:TSubTask = New TSubTask SubTask.SubTaskID = record.GetInt(0) SubTask.STName = record.GetString(1) SubTask.STOrder = record.GetInt(2) SubTask.STMemo = record.GetString(3) SubTask.STCreateDate = record.GetString(4) SubTask.STDueDate = record.GetString(5) SubTask.STCompletedDate = record.GetString(6) SubTask.STLastUpdatedDate = record.GetString(7) SubTask.STCancelled = record.GetInt(8) SubTask.MainTaskID = record.GetInt(9) SubTask.TMid = record.GetInt(10) DebugLog "Start of Data for SubTask record" DebugLog "SubTaskID = " + SubTask.SubTaskID DebugLog "STName = " + SubTask.STName DebugLog "STOrder = " + SubTask.STOrder DebugLog "STMemo = " + SubTask.STMemo DebugLog "STCreateDate = " + SubTask.STCreateDate DebugLog "STDueDate = " + SubTask.STDueDate DebugLog "STCompletedDate = " + SubTask.STCompletedDate DebugLog "STLastUpdatedDate = " + SubTask.STLastUpdatedDate DebugLog "STCancelled = " + SubTask.STCancelled DebugLog "MainTaskID = " + SubTask.MainTaskID DebugLog "TMID = " + SubTask.TMid DebugLog "End of Data for SubTask record" list.AddLast(SubTask) Next EndIf Return list End Function End Type