Custom Listbox

Hello All,

I am looking for a custom listbox that will allow me to freeze a column (the far left one or more is fine) and set individual cell properties.
I looked into the excellent Einhugur StyleGrid and I thought I had found what I was looking for. Unfortunately it needs a lot of updating between Retina and the 64 bit.

Any third party options out there that you guys know about?

Thanks,

Craig

Not sure if it supports column locking, but Mergeable Listbox may be an option.

No it does not.

Several years ago I tried to fake it using 2 listboxes… But I could not get scrolling and row highlighting synchronized between the two listboxes in all situations … In some situations there was a noticeable lag… For the in house app I was working on at the time, it was good enough so I did not keep at it, but the lag was enough not be commercially acceptable.

I would really like to add that feature to the Mergeable Cell listbox. If I have time I might revisit that and see if I can get it to work in the next few months.

  • Karen

Hi @Tanner Lee I appreciate the tip.

Hi @Karen Atkocius ~ seems like we both need the same sort of thing. If you do work this out sooner rather than later please let me know! :slight_smile:
I went down the same road of trying to sync the two listboxes and it was not…pleasing.

Any other suggestions?

Thanks.

Craig, are you talking about merely resizing the other non-frozen columns as the ListBox is resized, with one or more N frozen columns on the left? Or are you talking about as a current cell cursor moves off the right, the first non-frozen column on the left disappears? Or are you talking about something completely different.

If you mean; not allowing the left column to resize, then this should do it:

Me.Column(0).UserResizable = False

If you want to keep the left column where it is while you can scroll the rest horizontally, set the size of the first column to 0. Then add another listbox on the left and set the first column to * and all the others to 0.

Then in the CellBackGroundPaint of the right Listbox, something like this:

  Static Cnt As Integer
  If Cnt <> Me.ListCount Then
    Cnt = Me.ListCount
    ListBox1.Cell(-1,-1) = Me.Cell(-1,-1)
  End If
  
  Static Idx As Integer
  If Idx <> Me.ListIndex Then
    Idx = Me.ListIndex
    ListBox1.ListIndex = Idx
  End If
  
  Static Pos As Integer
  If Pos <> Me.ScrollPosition Then
    Pos = Me.ScrollPosition
    ListBox1.ScrollPosition = Pos
  End If

(Just to give you the idea. There’s a lot missing like selected row colors, the other way around etc.)

If you prefer a custom Listbox, I think piDog’s Dataview can do it.

I think he means being able to freeze the rightmost column so you can scroll teh other columns horizontally… and of course be able to scroll all of it vertically… As you can with excel…

I don’t think it can’t be done with a single listbox. You need two. In that case scrolling vertically with the rows in sync with with an external scrollbar is not hard … but there are a lot more syncing issues with vertical scrolling different ways and highlighting. No sure about inserting and deleting rows… i did not try that because of other issues.

  • Karen

[quote=229814:@Karen Atkocius]I think he means being able to freeze the rightmost column so you can scroll teh other columns horizontally… and of course be able to scroll all of it vertically… As you can with excel…

[/quote]
I meant leftmost column

a container control containing 2 listboxes, and 2 scrollbars (one vertical and one hrizontal)
one listbox at the left has only one column, and both listboxes have no scrollbars
you scroll the listboxes in the change event of the scrollbars, for the two listboxes if you change the vertical scrollbar
and only for the right listbox if you change the horizontal scrollbar.

[quote=229821:@Jean-Yves Pochez]a container control containing 2 listboxes, and 2 scrollbars (one vertical and one hrizontal)
one listbox at the left has only one column, and both listboxes have no scrollbars
you scroll the listboxes in the change event of the scrollbars, for the two listboxes if you change the vertical scrollbar
and only for the right listbox if you change the horizontal scrollbar.[/quote]

In theory yes… I tried that … In practice the devil is in the details and not so simple.

  • Karen

I am not convinced of that, I’ll play around with that some. I would think it would be easier than trying to keep two ListBoxes in sync. I am sure that could be done as well, but the syncing issues would be a nightmare to keep track of IMO.

I’d think you could do it with a single Listbox if you turn off horizontal scrolling and virtually scroll the data yourself. But the performance issues there would probably be horrific.

On the other hand, I wonder how easy it would be to adapt Data-On-Demand ListBox for that…

You COULD do it easily in a single listbox for a special case…that all columns were the same width. (And Kem I know the performance would be acceptable for that)… but that is far rom general purpose.

Because I thought that dealing with different width columns would be a nightmare when horizontal scrolling I did not go down that path.

I thought one would have to fight with the complexity of the column width specifications and how the listbox handles them- that you would always be fighting the built-in routines. I was far from sure that as a winnable fight.

Maybe it would not be that bad. Perhaps i will try it after I finish my current project.

It would be a great feature for Xojo to add…And failing that , they provide a way to sync two listboxes.

  • Karen

I’m messing with it right now, using one list box, having some success. I haven’t tried it with live data, but test data with the column number in each cell the performance is instantaneous on Windows. Using an old routine to detect the number of visible rows, converting it to detect the number of visible columns, which is a bit tricky because the rows are all the same size, columns can and usually are different widths.

Are you scrolling continuously horizontally or by column widths?
If you can do a smooth horizontal scroll as the listbox normally does while freezing the left column I will be impressed!

  • Karen

Just by whole column, but that is how Excel behaves. Continuous scrolling, showing partial columns would be a big performance hit, especially on Cocoa. Don’t think that is really workable given the current ListBox. But really a grid, table or listbox is meant to show discrete tabular data, so I don’t see the point of showing partial columns of tabular data with continuous scrolling.

The smooth scrolling is a big why i did not think it was doable… I wanted to keep the horizontal scrolling behavior the same as the built-in listbox. Doing it by column is much more approachable!

  • karen

How about handling the scrolling yourself. Then you have an opportunity to change column widths for the affect. You will need a dummy first column that grows with horizontal scroll and you’ll need to smartly collapse the non-frozen columns. You also need to CellTextPaint the partially collapsed columns so the text slides left.

The real challenge I think is capturing all the ways that might scroll, which I think are only…
MouseWheel
ScrollBars
Resized
Set ScrollPositionX

I only handled MouseWheel in my test (easiest). For ScrollBars you’ll need to add your own to drive the Listbox. For Resizing there’s no event on Listbox, you’ll have to call an update from the Windows or ContainerControls Resizing event. For setting ScrollPositionX, that’s a Property which can’t be pragmatically intercepted, so create a MyScrollPositionX and only use that.

This creates a ‘2’ column Listbox where column 0 just pads the horizontal scroll, column 1 is a frozen 200px column, and column 2 is 1000px and slides underneath. I’m sure there’s more edge cases than I’ve pointed out here.

[code]//Listbox events
Sub Open()
me.ColumnCount = 3
me.ColumnWidths = “0,200,1000”
for i As integer = 0 to 100
me.AddRow Array(" ", Str(i), “sigmund sore to fail in the light”)
next
me.ScrollBarHorizontal = true
End Sub

Function MouseWheel(X As Integer, Y As Integer, deltaX as Integer, deltaY as Integer) As Boolean
me.ScrollPosition = me.ScrollPosition + deltaY
me.ScrollPositionX = me.ScrollPositionX + deltaX
me.ColumnWidths = Str(me.ScrollPositionX) + “,200,” + Str(1000-me.ScrollPositionX)
return true
End Function

Function CellTextPaint(g As Graphics, row As Integer, column As Integer, x as Integer, y as Integer) As Boolean
if column = 2 then
g.DrawString(me.Cell(row, column), x-me.ScrollPositionX, y)
return true
end
End Function

//test updating from Window event
Sub Resizing()
lb.ColumnWidths = Str(lb.ScrollPositionX) + “,200,” + Str(1000-lb.ScrollPositionX)
End Sub[/code]

Hi Merv ~ Karen is correct. I want to freeze the left hand column(s) and be able to scroll right for as far as I like.

Wow! There is a lot here to process. Thank you my dear Xojo family. It is this kind of help and response that continues to reinforce in my mind that, while not perfect, Xojo is definitely the right choice for me!

@Merv Pate I am looking forward to seeing whatever you come up with.

And @Kem Tekinay that is an interesting idea about controlling the horizontal scrolling myself. Never crossed my mind. I will play with that. Thanks!