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*}">
/// <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(); } }

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
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.
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!!!!
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]
My code is identical more or less. The header in my ListView is:
To post code BTW, enclose it in pre tags.
It is possible to have this update when the GridView is resized (i.e. when the window is resized thus increasing the GridView)?
Plz Check out the following link.
http://www.ontheblog.net/CMS/Home/tabid/36/EntryID/37/Default.aspx
Thanks, that looks to be a more robust solution.
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
Without looking it in depth I’m not sure. I tend to use XCeed’s DataGrid (free version no longer available though).