Mar
11
2009

WPF: GridView Column Width Calculator



Comments available as RSS 2.0

The GridView in WPF isn’t bad, but is pretty basic compared to the one in ASP.NET. There’s isn’t really a decent method for setting column width, so I wrote this converter to calculate the width needed to fill the parent ListView.

If you call it with no parameters, it’ll take up the remaining width in the ListView:

// fills remaining width in the ListView
<GridViewColumn Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Converter={StaticResource WidthConverter}}">

If you use an integer as a parameter, the value will act as the minimum width

// fills remaining width in the ListView, unless the remaining width is less than the parameter
<GridViewColumn Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Converter={StaticResource WidthConverter},ConverterParameter=200}">

Or, you can specify a GridView type width with an asterisk, and the percentage width of the ListView will be returned

// calculates 30% of the ListView width
<GridViewColumn Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Converter={StaticResource WidthConverter},ConverterParameter=0.3*}">


Download Source

/// <summary>
/// Calculates the column width required to fill the view in a GridView
/// For usage examples, see http://leghumped.com/blog/2009/03/11/wpf-gridview-column-width-calculator/
/// </summary>
public class WidthConverter : IValueConverter {
    /// <summary>
    /// Converts the specified value.
    /// </summary>
    /// <param name="value">The parent Listview.</param>
    /// <param name="type">The type.</param>
    /// <param name="parameter">
    /// If no parameter is given, the remaning with will be returned.
    /// If the parameter is an integer acts as MinimumWidth, the remaining with will be returned only if it's greater than the parameter
    /// If the parameter is anything else, it's taken to be a percentage. Eg: 0.3* = 30%, 0.15* = 15%
    /// </param>
    /// <param name="culture">The culture.</param>
    /// <returns>The width, as calculated by the parameter given</returns>
    public object Convert(object value, Type type, object parameter, CultureInfo culture) {
        if(value == null) return null;
        ListView listView = value as ListView;
        GridView grdView = listView.View as GridView;
        int minWidth = 0;
        bool widthIsPercentage = parameter != null && !int.TryParse(parameter.ToString(), out minWidth);
        if(widthIsPercentage) {
            string widthParam = parameter.ToString();
            double percentage = double.Parse(widthParam.Substring(0, widthParam.Length - 1));
            return listView.ActualWidth * percentage;
        } else {
            double total = 0;
            for(int i = 0; i < grdView.Columns.Count - 1; i++) {
                total += grdView.Columns[i].ActualWidth;
            }
            double remainingWidth = listView.ActualWidth - total;
            if(remainingWidth > minWidth) { // fill the remaining width in the ListView
                return remainingWidth;
            } else { // fill remaining space with MinWidth
                return minWidth;
            }
        }            
    }
 
    public object ConvertBack(object o, Type type, object parameter, CultureInfo culture) {
        throw new NotSupportedException();
    }
}
Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay

Comments

  1. Michi says:

    Hi,
    nice code, but it doesn’t work in my project.
    I think i’ve a problem with this line:
    {Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}}
    because the variable “object value” in the method is always null.

    Can you post a sample xaml code please?

    Michi

    • Echilon says:

      I didn’t experience that problem, but I’ve amended the sample with a check for null. Try using that. The value parameter should be the ListView, but if the Window/Control hasn’t loaded yet that might cause an exception.

  2. Michi says:

    Hey,

    thanks for your response, but as “value” is always null, the check for null just lets the method return null after the first line…
    Perhaps we didn’t implement our listview in the correct way…here´s one of the listviews:

    The “WidthConverter” Resource is also set at the beginning of the xaml file.

    Do we have to set any attributes to the listview?

    Thanks for your help!!!!

  3. Michi says:

    ooops,

    sorry but the xaml code seems to be detected as html code. here we go again(this time with [] instead):

    [ListView Name="fp_userList" Margin="10,0,10,10" SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectionChanged="fp_userList_SelectionChanged"]
    [ListView.View]
    [GridView ]
    [GridViewColumn Header="User" Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Converter={StaticResource WidthConverter}}"/]
    [/GridView]
    [/ListView.View]
    [/ListView]

  4. Echilon says:

    My code is identical more or less. The header in my ListView is:

    <ListView x:Name="lstResources" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" GridViewColumnHeader.Click="OnColumnHeaderClick"
    	  SelectionMode="Single" ItemsSource="{Binding}" SelectedValuePath="resourceid">

    To post code BTW, enclose it in pre tags. :)

  5. Luke says:

    It is possible to have this update when the GridView is resized (i.e. when the window is resized thus increasing the GridView)?

  6. whuzx says:

    HI
    thanks for your code.
    but I have a problem is that when the System.Globalization.CultureInfo changed ,

    “double percentage = double.Parse(widthParam.Substring(0, widthParam.Length – 1));”

    will not parse correctly.if we change the current CultureInfo to Polish form.we could not get the respect result

    how to handle this problem ?

    thank you

Leave a Comment

Login using OpenID or enter your details below to leave a comment.

OpenID
Anonymous


Comment

Powered by WP Hashcash