BLOG - Filter: WPF Grid
WPF Grid: Percentaged columns height/width
Samstag, 18. Juli 2009, Christoph Ertl

WPF 3.5 SP1When defining rows of a WPF grid you can use several ways to set the height of the row. Automatic, absolute values or relative values. But there's no notation for percent values.

But instead of writing Height="25%" you just use the relative notation.

<Grid.RowDefinitions>
 
<RowDefinition Height="25*" />
 
<RowDefinition Height="75*" />
</
Grid.RowDefinitions>

 

Using this notation with databinding

Assume we have a simple data class

public class Data {
 
public int Percent1 { get; set; }
 
public int Percent2 { get; set; }
}

and bind the two properties to the two rows of the grid

<Grid.RowDefinitions>
 
<RowDefinition Height="{Binding Path=Percent1}" />
 
<RowDefinition Height="{Binding Path=Percent2}" />
</Grid.RowDefinitions>

and assign the DataContext property

DataContext = new Data() { Percent1=25, Percent2=75 };

we get a grid with the first row's height set to 25 and second row's height set to 75 in absolute values. As you can see the rows have the correct height but they do not use the whole height of the grid. To get this fixed we need to use the star notation again.

We need to convert the values to get the visual result we want. And the conversion must be done at the data binding because it's part of the presentation of the data and not the data itself.
When working with WPF (not only in WPF) you should always consider if the logic is part of the presentation or the data being presented.

Converting the bound values

To convert the values we create a simple converter class implementing the IValueConverter interface placed in the namespace System.Windows.Data. We just need to implement the convert method adding the star at the end of the value.

class PercentConverter : IValueConverter {
 
public object Convert(object value,
                       
Type targetType,
                        object parameter, 
                        CultureInfo culture) {
   
return value.ToString() + "*";
  }

  public object ConvertBack(....)
}

When we now use the converter for databinding

<Grid.RowDefinitions>
 
<RowDefinition Height="{Binding Path=Percent1,Converter={StaticResource PercentConverter}}" />
 
<RowDefinition Height="{Binding Path=Percent2,Converter={StaticResource PercentConverter}}" />
</Grid.RowDefinitions>

we get the result we wanted to have.