0

I have ListView with five columns. And those columns have width. But there is a problem with empty space after last column. I want to get rid of it. Unfortunatelly, I was't able to find out how to do that.

Situation now:

image

As you can see, there is empty space after column 5. I simply want to set columns 2 - 5 static width (let's say 100), align them somehow to right and let column 1 fill the rest of remaining space. So when I resize the main window, those four columns should have still the same size, but first one should be wider.

XAML:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <ListView Name="ListView1" Grid.Column="0" Width="Auto" >
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Column1" Width="200"/>
                <GridViewColumn Header="Column2" Width="100"/>
                <GridViewColumn Header="Column3" Width="100"/>
                <GridViewColumn Header="Column4" Width="100"/>
                <GridViewColumn Header="Column5" Width="100"/>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>
dymanoid
  • 14,771
  • 4
  • 36
  • 64
Ano Nymous
  • 11
  • 4
  • Possible duplicate of [How can I get a ListView GridViewColumn to fill the remaining space in my grid?](https://stackoverflow.com/questions/8331940/how-can-i-get-a-listview-gridviewcolumn-to-fill-the-remaining-space-in-my-grid) – Corentin Pane Sep 23 '19 at 15:48
  • Possible duplicate of [ListView column auto sizing](https://stackoverflow.com/questions/2834971/listview-column-auto-sizing) – dymanoid Sep 23 '19 at 15:48

3 Answers3

1

Here's a solution that works but it's a little bit involved. The other columns apart from the first one must share equal width. here is the XAML

ListView Name="ListView1" Grid.Column="0" Width="auto" SizeChanged="ListView1_SizeChanged">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Column1" Width="200"/>
                <GridViewColumn Header="Column2" Width="{Binding EqualSize}"/>
                <GridViewColumn Header="Column3" Width="{Binding EqualSize}"/>
                <GridViewColumn Header="Column4" Width="{Binding EqualSize}"/>
                <GridViewColumn Header="Column5" Width="{Binding EqualSize}"/>
            </GridView>
        </ListView.View>
    </ListView>

Now define the "EqualSize" property based on the Actual width of the ListView. This definition should be updated on the SizeChanged event handler of the ListView. Here's the code:

private double _equalSize;
    public double EqualSize {
        get { return _equalSize; }
        set {
            if (_equalSize!=value) {
                _equalSize = value;
                RaisePropertyChanged();
            }
        }
    }
    private void ListView1_SizeChanged(object sender, SizeChangedEventArgs e) {
        EqualSize = (colDef.ActualWidth - 200) / 4;
    }// The magic number 200 is the size of the first column and 4 is the number of columns that share the same size

You can implement this from the code-behind file (recommended) or from a view model class

Ndubuisi Jr
  • 461
  • 6
  • 13
  • Hi, tried this before, but there is always an error in error list saying I cannot convert "*" to Length. I can build it though, but when I run application it throws an 'System.Windows.Markup.XamlParseException' - Provide value on 'System.Windows.Baml2006.TypeConverterMarkupExtension' threw an exception. – Ano Nymous Sep 23 '19 at 17:46
  • Yeah... I've figured it out. Check my answer, I've updated it. – Ndubuisi Jr Sep 23 '19 at 20:16
0

Try taking up a percentage instead of fixed size.

private void ListView_SizeChanged(object sender, SizeChangedEventArgs e)
{
    ListView listView = sender as ListView;
    GridView gridView = listView.View as GridView;

    var width = listView.ActualWidth - SystemParameters.VerticalScrollBarWidth;

    var column1 = 0.40;
    var column2 = 0.15;
    var column3 = 0.15;
    var column4 = 0.15;
    var column5 = 0.15;

    gridView .Columns[0].Width = width*column1;
    gridView .Columns[1].Width = width*column2;
    gridView .Columns[2].Width = width*column3;
    gridView .Columns[3].Width = width*column4;
    gridView .Columns[4].Width = width*column5;
}
Patrick95
  • 110
  • 12
0

I inspected a lot of code and wrote yet another MVVM solution. This applicable for one column with "*".

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <ListView Name="ListView1" Grid.Column="0" Width="Auto" >
        <ListView.Resources>
            <conv:GridViewColumnWidthConverter x:Key="GridViewColumnWidthConverter"/>
        </ListView.Resources>
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Column1">
                    <GridViewColumn.Width>
                        <MultiBinding Converter="{StaticResource GridViewColumnWidthConverter}" ConverterParameter="*">
                            <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListView}}" Path="ActualWidth" />
                            <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type GridView}}" />
                            <Binding RelativeSource="{RelativeSource Self}"/>
                        </MultiBinding>
                    </GridViewColumn.Width>
                </GridViewColumn>
                <GridViewColumn Header="Column2" Width="100"/>
                <GridViewColumn Header="Column3" Width="100"/>
                <GridViewColumn Header="Column4" Width="100"/>
                <GridViewColumn Header="Column5" Width="100"/>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

Converter:

public class GridViewColumnWidthConverter : IMultiValueConverter
{
    private static readonly System.Reflection.PropertyInfo s_piDesiredWidth;

    static GridViewColumnWidthConverter()
    {
        var pi = typeof(GridViewColumn).GetProperty("DesiredWidth",
            System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        Debug.Assert(pi != null);
        s_piDesiredWidth = pi;
    }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter is string param && param == "*" && values.Length==3 && values[0] is double actualWidth && actualWidth > 0d)
        {
            if (values[1] is GridView gridView && values[2] is GridViewColumn column && s_piDesiredWidth != null)
            {
                double w = 0d;
                foreach (var col in gridView.Columns)
                {
                    if (col == column)
                        continue;
                    w += col.ActualWidth > 0 ? col.ActualWidth : (double)s_piDesiredWidth.GetValue(col);
                }
                double desiredWidth = actualWidth - w;
                return desiredWidth > 100 ? desiredWidth - 25/*scrollbar width*/ : double.NaN;
            }
        }
        return double.NaN;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return null;
    }
}
VgrSoft
  • 1
  • 1