Xojo ListBox Drag/Drop

Dragging rows from one ListBox to another.
How do I ensure my dragged rows are inserted in the order they came? Bit of logic that’s eluding me this morning, likely due to the way things move as each row is inserted…

DrawRow in source ListBox

For Each i As Integer In Me.SelectedRows
  drag.AddItem(0, 0, 20, 4)
  drag.Text = Me.Cell(i, -1) // get text
Return True // allow the drag

DropObjectOnRow in receiving ListBox

  If obj.TextAvailable Then
    Me.InsertRow(row, "")
    Me.Cell(row, -1) = obj.Text
  End If
Loop Until Not obj.NextItem

SelectedRows extension:

Function SelectedRows(Extends LB As ListBox) As Integer()
Dim SR() As Integer
For i As Integer = 0 To LB.ListCount - 1
  If LB.Selected(i) Then SR.Append(i)
Next i
Return SR

insert will do the wrong thing after you have inserted one as it will push the previously added row down - not what you want (its like “insert before”)
I think you’ll need to add after the last inserted row all the time in the loop

dim whereToAdd as integer = row
  If obj.TextAvailable Then
    Me.InsertRow(whereToAdd, "")
    Me.Cell(row, -1) = obj.Text
    whereToAdd = me.lastIndex + 1 // after the last one we added
  End If
Loop Until Not obj.NextItem

or something like this

IF you are just getting text you could gather them all into an array then insert that in reverse order

dim received() as string
  If obj.TextAvailable Then
    received.append = obj.Text
  End If
Loop Until Not obj.NextItem
for i as integer = received.ubound downto 0
    Me.InsertRow(row, "")
    Me.Cell(row, -1) = received(i)

Thanks, Norm.

Ended up with:

Function DragRow(drag As DragItem, row, As Integer) As Boolean
  Dim SRows() As Integer = Me.SelectedRows
  For I As Integer = SRows.UBound DownTo 0
    drag.AddItem(0, 0, 20, 4)
    drag.Text = Me.Cell(SRows(i), -1)
Return True


Function DropObjectOnRow(x As Integer, y As Integer, obj As DragItem, action As Integer, parentRow As Integer, location as ListBox.DropLocations)
  If obj.TextAvailable Then
    Me.InsertRow(row, "")
    Me.Cell(row, -1) = obj.Text
  End If
Loop Until Not obj.NextItem

Strangley, couldn’t write:
drag.Text = Me.Cell(Me.SelectedRows(i), -1)
but I could write
For I As Integer = Me.SelectedRow.UBound DownTo 0

So the Extended method behaves a BIT like a the object it’s supposed to be, but not entirely…

one of the issues with how Xojo works with methods that return an array extensions work
you’d have to break that into 2 lines at least
you cannot call the method and index into the array on the same line
it would have to look like

the first () is “the call to the method” and the (i) is indexing into the array that method call returns

and thats just not how Xojo handles this :frowning:

so you do have to write

Right. Sounds similar to my pet peeve that I can’t write:
Dim FirstWord As String = LongString.Split(" ")(0)
or similarly
Dim SplitString() as String = ("Hi Mom!").Split(" ")

As I could in .NET…

Not a big deal, but takes you by surprise the first time.

I started recently to use something like
Dim FirstWord As String = LongString.nthField(" ",1) // First index is 1 for some reason here!

For that first scenario.

Ok, more fun with drag/drop in ListBoxes.

If I have drag/drop enabled, AND drag reorder enabled, how do I force the lb to one of the modes? It seems the drag/drop overrides the drag reorder so that now dragging to reorder rows, just does a regular drag/drop (with a copy of the rows). Obviously it’s easy enough to test if I’m dropping within the same listbox or a different one, but it looks like the drag/drop gets activated immeditaely without the option of recordering rows.
Is there a way to “disable” the drag/drop function until the cursor has moved outside the listbox, and use drag reorder until then? (and I guess cancel the drag reorder if I’ve moved outside the listbox). Whew! getting complicated!

Yeah Xojo/REALbasic has never supported indexing into an array returned by a method immediately on the same line as the method call

It could but … you know … compiler engineer etc
And I doubt it has that many folks who would request it so its low priority
About the same as generics and a few other things that a compiler person could fix

The listbox is such a swiss army knife of stuff that sometimes you get into these binds

IF you enable drag reorder then other stuff wont be handleable as you cant override the built in drag reorder

So you may need to turn OFF drag reorder and handle doing that yourself

Actually, it’s the other way around. Drag Reorder doesn’t work if there’s a DragRow event it seems. Or if you return False at the beginning of the DragRow Event then the DragReorder works again.

I’ll have to check to see that DragReorder also moves row tags (I’m sure it would…)

Yeah its messy as hell if you try to have some stuff automatically handled & some stuff not

Been there done that tore my hair out (really)

1 Like