I'm not sure if there is any other straight-forward solution (although I'm almost sure there is not any direct way to go). The following solution can be considered as a work-around but it's actually a beautiful one.
You can make the second column (or generally the last column) fill the remaining space by using some Binding
to bind the ListView's Columns' Width to the Grid
's Columns' Width. Yes we know that only Grid
has some features which no other controls have. Here are the detailed steps:
- Firstly, we need a
Grid
having the same number of columns with the ListView. The ListView of course should be placed inside this Grid
. By using Grid.ColumnSpan
we can make the ListView fill the whole Grid.
- Secondly, bind the Width of all the Grid columns to the ActualWidth of the corresponding ListView columns except the last Column. The last column of the Grid should have
Width
set to *
(fill the remaining space).
- Lastly, you need some dummy element (such as a Border) put in the last column of the Grid. We need this dummy element to get its
ActualWidth
, so that we can bind the last ListView column's Width to that ActualWidth
. A ColumnDefinition
of the Grid also has the property ActualWidth
but it is not a dependency property and also it does not have any property changed notifying mechanism (so we cannot use that property).
Now is the working code:
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ActualWidth,ElementName=firstCol}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- the dummy element -->
<Border Grid.Column="1" Name="dummy" Margin="5"></Border>
<ListView HorizontalContentAlignment="Stretch" Grid.ColumnSpan="2"
ItemsSource="{Binding }">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" x:Name="firstCol">
<GridViewColumnHeader Content="Filename"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Filename}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="{Binding ActualWidth, ElementName=dummy}">
<GridViewColumnHeader Content="Pages"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Pages}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListView>
</Grid>
Note that your original ListView
may be placed in some Grid (you set its Grid.Row="0"
). However when using this trick, the ListView
should always be placed inside a wrapper Grid and you have to set Grid.Row="0"
(although this is set by default) for this wrapper Grid
instead. I mean this wrapper Grid will be placed in your original Grid
(if any present).
Update: To make it dynamic like as a Grid
, you need more dummy elements (we use just 1 dummy Border for the last column in the code above). Each dummy elements will be put in each Grid's column. As I explained, we need this to proxy the ActualWidth of the Grid's column, although ColumnDefinition
also has an ActualWidth
property but it cannot be used in Binding (does not support any change notification). Here is the code:
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<!-- the dummy elements -->
<Border Grid.Column="0" Name="dummy1" Margin="5"></Border>
<Border Grid.Column="1" Name="dummy2" Margin="5"></Border>
<!-- your ListView -->
<ListView HorizontalContentAlignment="Stretch" Grid.ColumnSpan="2"
ItemsSource="{Binding }">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Width="{Binding ActualWidth, ElementName=dummy1}">
<GridViewColumnHeader Content="Filename"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Filename}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="{Binding ActualWidth, ElementName=dummy2}">
<GridViewColumnHeader Content="Pages"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Pages}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListView>
</Grid>