Since List1's rowsource is fields from a cursor, you
have to delete the cursor rows.
Also, if list2's rowsourcetype is 0, just use the
additem() method to add the first column and then the
addlistitem() method to add the contents of the second column.
Here's an example that shows moving single and multiple
selected items:
You should have no problem figuring out how to move items
back to the source listbox.
oForm = CREATEOBJECT("MyForm"

oForm.SHOW()
READ EVENTS
DEFINE CLASS MyForm AS FORM
DATASESSION = 2
WIDTH = 430
AUTOCENTER = .T.
CAPTION = "Listbox mover example"
* The source listbox
ADD OBJECT lstSource AS LISTBOX WITH ;
LEFT = 5, ;
WIDTH = 200, ;
HEIGHT = 200, ;
ROWSOURCE = "test.ListItem1,ListItem2", ;
ROWSOURCETYPE = 6, ;
COLUMNCOUNT = 2, ;
MULTISELECT = .T., ;
INTEGRALHEIGHT = .T., ;
FONTNAME = "courier new"
* The target listbox
ADD OBJECT lstTarget AS LISTBOX WITH ;
LEFT = THIS.lstSource.LEFT + THIS.lstSource.WIDTH + 20, ;
WIDTH = 200, ;
HEIGHT = 200, ;
COLUMNCOUNT = 2, ;
INTEGRALHEIGHT = .T., ;
SORTED = .T., ;
FONTNAME = "courier new"
* Command button to move a single item from source to target
ADD OBJECT cmdSnglMover AS COMMANDBUTTON WITH ;
TOP = THIS.lstSource.TOP + THIS.lstSource.HEIGHT + 10, ;
HEIGHT = 24, ;
AUTOSIZE = .T., ;
CAPTION = "Move Single Selects"
* Command button to move multiple items from source to target
ADD OBJECT cmdMultiMover AS COMMANDBUTTON WITH ;
TOP = THIS.cmdSnglMover.TOP, ;
LEFT = 150, ;
HEIGHT = 24, ;
AUTOSIZE = .T., ;
CAPTION = "Move Multiple Selects"
* Command button to reset listboxes and data cursor
ADD OBJECT cmdReset AS COMMANDBUTTON WITH ;
TOP = THIS.cmdSnglMover.TOP, ;
LEFT = 300, ;
HEIGHT = 24, ;
AUTOSIZE = .T., ;
CAPTION = "Reset"
* Form and context settings
PROCEDURE LOAD
SET DELETED ON
SET SAFE OFF
CREATE CURSOR test (ListItem1 C(8), ListItem2 C(8))
INDEX ON ListItem1 TAG ListItem1
THIS.LoadData()
ENDPROC
* Load lstSource's data cursor
PROCEDURE LoadData
ZAP IN "test"
FOR i = 1 TO 100
INSERT INTO test (ListItem1,ListItem2) VALUES ("Col1 "+(STR(i,3)),"Col2 "+(STR(i,3)))
NEXT
ENDPROC
* Form is initing
PROCEDURE INIT
THIS.lstSource.REQUERY()
ENDPROC
* Form is dying
PROCEDURE DESTROY
CLEAR EVENTS
USE IN "test"
ENDPROC
* Move a single selected items
PROCEDURE cmdSnglMover.CLICK
WITH THISFORM
IF .lstSource.LISTINDEX <> 0
.lstTarget.ADDITEM(.lstSource.LISTITEM(.lstSource.LISTINDEX,1))
.lstTarget.ADDLISTITEM(.lstSource.LISTITEM(.lstSource.LISTINDEX,2),;
.lstTarget.LISTCOUNT,2)
DELETE NEXT 1 IN "test"
.lstSource.REQUERY()
ENDIF
ENDWITH
ENDPROC
* Move any multiple selected items
PROCEDURE cmdMultiMover.CLICK
LOCAL i, lbMoved, lnDeleteRecs
LOCAL ARRAY laDeleteRecs[1]
lnDeleteRecs = 0
WITH THISFORM
FOR i = 1 TO .lstSource.LISTCOUNT
IF .lstSource.SELECTED(i)
* Save the record # of each selected item
lnDeleteRecs = lnDeleteRecs + 1
DIME laDeleteRecs[lnDeleteRecs]
=SEEK(.lstSource.LISTITEM(i,1),"test"

laDeleteRecs[lnDeleteRecs] = RECNO("test"
.lstTarget.ADDITEM(.lstSource.LISTITEM(i,1))
.lstTarget.ADDLISTITEM(.lstSource.LISTITEM(i,2), ;
.lstTarget.LISTCOUNT,2)
lbMoved = .T.
ENDIF
NEXT
IF lbMoved
FOR i = 1 TO lnDeleteRecs
DELETE RECORD (laDeleteRecs[ i ]) IN "test"
NEXT
.lstSource.REQUERY()
ENDIF
ENDWITH
ENDPROC
* Reset the listboxes and data cursor
PROCEDURE cmdReset.CLICK
WITH THISFORM
.LoadData()
.lstSource.CLEAR()
.lstTarget.CLEAR()
.lstSource.LISTINDEX = 0
.lstTarget.LISTINDEX = 0
.lstSource.REQUERY()
ENDWITH
ENDPROC
ENDDEFINE
'We all must do the hard bits so when we get bit we know where to bite'
