Let's say I have the following ListView:
<ListView ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.View>
<GridView>
<GridViewColumn Header="Something"
DisplayMemberBinding="{Binding Path=ShortText}" />
<GridViewColumn Header="Description"
DisplayMemberBinding="{Binding Path=VeryLongTextWithCRs}" />
<GridViewColumn Header="Something Else"
DisplayMemberBinding="{Binding Path=AnotherShortText}" />
</GridView>
</ListView.View>
</ListView>
I'd like the short text columns to always fit in the screen, and the long text column to use the remaining space, word-wrapping if necessary.
Is that possible?
There is no easy way to do this with a GridListView since it doesn't support setting the width of a column to "*" (fill remaining space).
Here is a discussion of how you could fake it by using an IValueConverter to set the width of the column to TotalListWidth - SumOfColumnWidths
On the other hand, have you considered using a DataGrid instead? This will support the kind of layout you are looking for, though is a considerably heavier control. It is also only native in .NET 4 - though you can get an equivalent for 3.5 through the WPF Toolkit.
<Grid Name="dummygrid" Visibility="Hidden">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Name="dummywidth1"></Border>
<Border Grid.Column="1" Name="dummywidth2"></Border>
<Border Grid.Column="2" Name="dummywidth3"></Border>
<Border Grid.Column="3" Name="dummywidth4"></Border>
<Border Grid.Column="5" Name="dummywidth5"></Border>
</Grid>
<ListView Name="Installer_LV" Grid.Row="1" ItemContainerStyle="{StaticResource LV_ItemStyle}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" AlternationCount="2">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource LV_HeaderStyle}">
<GridViewColumn Width="{Binding ElementName=dummywidth1, Path=ActualWidth}" DisplayMemberBinding="{Binding DisplayName}" >
<GridViewColumn.Header>
<GridViewColumnHeader Tag="DisplayName" Click="InstallerLV_HeaderClick">Name</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="{Binding ElementName=dummywidth2, Path=ActualWidth}" DisplayMemberBinding="{Binding Publisher}">
<GridViewColumn.Header>
<GridViewColumnHeader Tag="Publisher" Click="InstallerLV_HeaderClick">Publisher</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="{Binding ElementName=dummywidth3, Path=ActualWidth}" DisplayMemberBinding="{Binding Version}">
<GridViewColumn.Header>
<GridViewColumnHeader Tag="Version" Click="InstallerLV_HeaderClick">Version</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="{Binding ElementName=dummywidth4, Path=ActualWidth}" DisplayMemberBinding="{Binding Size}">
<GridViewColumn.Header>
<GridViewColumnHeader Tag="Size" Click="InstallerLV_HeaderClick">Size</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Header="Action" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Height="38" Width="130" Style="{DynamicResource RoundedButton}" Content="{Binding Status}" Tag="{Binding ModuleId}" HorizontalAlignment="Center" VerticalAlignment="Center" Click="onActionClick"></Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
In the above example i have used a dummy grid and split into 5 columns and using binding assign that size to "GridViewColum" by
Width="{Binding ElementName=dummywidth4, Path=ActualWidth}"
So that when the hidden dummy grid column size changes it will get reflect in gridview column size also.
Set Width="Auto"
on your GridViewColumns. However, due to virtualization you may encounter some problems with auto-sizing.
See this question.
So, long-story-short, if you want accurate auto-sizing of columns you'll need to recalculate your widths when the visible data changes, due to virtualization.
This works for me, toggling the Width
to ActualWidth
and then back to NaN
for any columns that don't have widths explicitly set. This will only work if the listview columns do not contain controls. I usually call this after data in the list has changed.
Public Shared Sub AutoResizeListView(lst As Windows.Controls.ListView)
Dim gv = DirectCast(lst.View, Windows.Controls.GridView)
For Each gvc In gv.Columns
If Double.IsNaN(gvc.Width) Then
gvc.Width = gvc.ActualWidth
gvc.Width = Double.NaN
End If
Next
End Sub
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With