-
Jan 26th, 2021, 08:47 PM
#1
Thread Starter
Member
Auto resize ListView columns to fit either the header text or content
If the ListView has no items this will resize the columns to fit the header text but if it has items it will resize the columns to fit the content if the content is wider than the header text.
Code:
''' <summary>
''' Automatically resizes a ListViews columns to fit either the column content or the column header text depending on which is the widest
''' </summary>
''' <param name="List_View"></param>
Public Sub AutoColumnResize(List_View As ListView)
Dim ColHeader As ColumnHeader
Dim HeaderTextLength As Integer
Dim MaxContentLength As Integer
For i = 0 To List_View.Columns.Count - 1
ColHeader = List_View.Columns(i)
HeaderTextLength = List_View.Columns(i).Text.Length
For inc = 0 To List_View.Items.Count - 1
MaxContentLength = Math.Max(MaxContentLength, List_View.Items(inc).SubItems(i).Text.Length)
Next
If MaxContentLength < HeaderTextLength Then
ColHeader.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize)
End If
Next
End Sub
Last edited by LucasCain; Jan 26th, 2021 at 08:50 PM.
-
Jan 26th, 2021, 09:08 PM
#2
Re: Auto resize ListView columns to fit either the header text or content
I haven't tested it specifically but wouldn't you just need to do this:
vb.net Code:
List_View.AutoResizeColumns(If(List_View.Items.Count = 0,
ColumnHeaderAutoResizeStyle.HeaderSize,
ColumnHeaderAutoResizeStyle.ColumnContent))
EDIT: Actually, I see that, if ColumnContent ignores the header, that may cut off a header that is longer that all the subitems in that column. The problem with your code is that it accounts only for the number of characters and not the pixel width of the text. For instance "iiii" has more characters than "www" and so would be considered longer by your code, although the latter actually takes up more pixels.
Last edited by jmcilhinney; Jan 26th, 2021 at 09:11 PM.
-
Jan 26th, 2021, 09:13 PM
#3
Thread Starter
Member
Re: Auto resize ListView columns to fit either the header text or content
Yes that looks much more simple
Oh well that was my first codebank post lol
-
Jan 26th, 2021, 09:46 PM
#4
Re: Auto resize ListView columns to fit either the header text or content
I just tested and the code I posted will indeed cut off a long column header if all subitems in that column are shorter. It seems an oversight that there isn't an option to consider both header and items automatically but that's the way it is. As such, your code is, in principle, better. It could do with a bit of improvement though. This should address all the issues:
vb.net Code:
Private Sub ResizeListViewColumns(listView As ListView)
Dim items = listView.Items.Cast(Of ListViewItem).ToArray()
Dim itemCount = items.Length
Dim g As Graphics
'Create a single Graphics object with which to measure text if and only if it is needed..
If itemCount > 0 Then
g = listView.CreateGraphics()
End If
For Each column As ColumnHeader In listView.Columns
'Assume that we're autosizing based on the header unless determined otherwise.
Dim style = ColumnHeaderAutoResizeStyle.HeaderSize
If itemCount > 0 Then
'Get the pixel width of the header text.
Dim headerWidth = g.MeasureString(column.Text, listView.Font).Width
'get the greatest pixel width of the subitems.
Dim maxSubItemWidth = items.Max(Function(item) g.MeasureString(item.SubItems(column.Index).Text, listView.Font).Width)
If maxSubItemWidth > headerWidth Then
style = ColumnHeaderAutoResizeStyle.ColumnContent
End If
End If
column.AutoResize(style)
Next
'Dispose the Graphics object if and only if we created one.
g?.Dispose()
End Sub
-
Jan 26th, 2021, 09:53 PM
#5
Re: Auto resize ListView columns to fit either the header text or content
You could even implement that code as an extension method:
vb.net Code:
Imports System.Runtime.CompilerServices
Public Module ListViewExtensions
<Extension>
Public Sub AutoResizeColumns(source As ListView)
Dim items = source.Items.Cast(Of ListViewItem).ToArray()
Dim itemCount = items.Length
Dim g As Graphics
'Create a single Graphics object with which to measure text if and only if it is needed..
If itemCount > 0 Then
g = source.CreateGraphics()
End If
For Each column As ColumnHeader In source.Columns
'Assume that we're autosizing based on the header unless determined otherwise.
Dim style = ColumnHeaderAutoResizeStyle.HeaderSize
If itemCount > 0 Then
'Get the pixel width of the header text.
Dim headerWidth = g.MeasureString(column.Text, source.Font).Width
'get the greatest pixel width of the subitems.
Dim maxSubItemWidth = items.Max(Function(item) g.MeasureString(item.SubItems(column.Index).Text, source.Font).Width)
If maxSubItemWidth > headerWidth Then
style = ColumnHeaderAutoResizeStyle.ColumnContent
End If
End If
column.AutoResize(style)
Next
'Dispose the Graphics object if and only if we created one.
g?.Dispose()
End Sub
End Module
That would allow you to call it on the ListView itself, just as you would call the existing instance method with the same name. If you pass an argument of type ColumnHeaderAutoResizeStyle then it will invoke the existing instance method and if you don't pass any parameters it will invoke this instance method.
vb.net Code:
'Call the instance method of the ListView class.
ListView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)
'Call our new extension method.
ListView1.AutoResizeColumns()
-
Jan 26th, 2021, 09:56 PM
#6
Thread Starter
Member
Re: Auto resize ListView columns to fit either the header text or content
After reading your post i was seeing that was the way to go using MeasureString thanks for updated version.
Last edited by LucasCain; Jan 26th, 2021 at 10:16 PM.
-
Jan 26th, 2021, 10:18 PM
#7
Re: Auto resize ListView columns to fit either the header text or content
Team effort, baby!
Actually, it occurred to me that that could be improved a little more. If there are no items then we can use the existing instance method, so we only need to use our own code if there are items:
vb.net Code:
Imports System.Runtime.CompilerServices
Public Module ListViewExtensions
<Extension>
Public Sub AutoResizeColumns(source As ListView)
Dim items = source.Items.Cast(Of ListViewItem).ToArray()
Dim itemCount = items.Length
If itemCount = 0 Then
source.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)
Return
End If
'Create a single Graphics object with which to measure all text.
Using g = source.CreateGraphics()
For Each column As ColumnHeader In source.Columns
'Assume that we're autosizing based on the header unless determined otherwise.
Dim style = ColumnHeaderAutoResizeStyle.HeaderSize
'Get the pixel width of the header text.
Dim headerWidth = g.MeasureString(column.Text, source.Font).Width
'get the greatest pixel width of the subitems.
Dim maxSubItemWidth = items.Max(Function(item) g.MeasureString(item.SubItems(column.Index).Text, source.Font).Width)
If maxSubItemWidth > headerWidth Then
style = ColumnHeaderAutoResizeStyle.ColumnContent
End If
column.AutoResize(style)
Next
End Using
End Sub
End Module
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|