Quick tip: Invalidate Listbox Header

I was looking for a way to redraw a Listbox header. In Xojo there is no method on the Listbox.
By calling the Invalidate method will redraw the entire Listbox. This can be very time-expensive when the Listbox has many graphical elements to be drawn in the cells.

One way to redraw a header is changing the text content of the header. When the content is set to what the content already is, the header will redraw itself.

This will redraw all the headers of Listbox1:
Listbox1.HeaderAt( 0 ) = Listbox1.HeaderAt( 0 )

Of course it is possible to create a convenience method that extends the Listbox. This way we can create our own InvalidateHeader method:

Public Sub InvalidateHeader(extends lb as Listbox)
    ' Just checking if we can actually draw the headers
    If lb = Nil Or Not lb.HasHeader Or lb.ColumnCount = 0 Then Return   

    ' By just setting one header, all headers will be redrawn.
    lb.HeaderAt(0) = lb.HeaderAt(0)
End Sub

I hope this little snippet is useful for someone.

6 Likes

Checking to see if the Listbox object is Nil is probably not necessary.
Since this method is an extension of the Listbox class, it will raise an nil-exception when used in your code…

Maybe you don’t want it to?

Well, when this code executes, the lb parameter will never be nil.

A window control can be nil by accessing a window control from an asynchronous event handler after the window has closed. It is entirely possible :slight_smile:

Couldn’t you just call invalidate and pass in the rect for the header?

rectControl.invalidate( left, top, width, height, redrawbackground)

That sounds interesting. I have not tried that yet.
My solution was merely a quick fix, and it works.
But with your solution you could target specific headers, instead of all of them.

1 Like

True, but when I access controls on other windows I usually check if the control is nil.

When I need to pass data to other windows I usually store the data in a window property.
Usually I use a dictionary object for that. I make it a Computed Property. When set, I can populate the corresponding fields. When the fields values change I update the dictionary.
In another window I can check if the dictionary object ≠ nil. That happens when my edit-window has some cancel button to close the window, discarding the changes.