tags:

views:

112

answers:

2

I have this XAML:

<Grid Background="LightYellow" Height="150" Width="150">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
</Grid>

And I'm trying to get the height of the second row like this:

height = grid.RowDefinitions[1].Height.Value;

But I get a 1. I tried ActualSize and it doesn't work either (returns 0). How can I get the height of the row?

Thanks!

A: 

What are you trying to do?

You might want to consider inheriting from the grid and overriding the measure and arrange methods, if you are trying to change the default layout.

Danny Varod
It's not that, I'm trying to make a control that draws itself based on the size of its parent. If it's a StackPanel it's pretty straight forward, but if it's a grid, I have to consider the height of the row that contains it and the width of the column.
Carlo
+2  A: 

First off, the reason Height.Value returns 1 is that Height is a GridLength, with a GridUnitType of Star. The 1 is from proportional star sizing (e.g. Height="2*", Height="3*", etc.). I.e. you can't read GridLength.Value in isolation: you have to read it in conjunction with the GridUnitType.

Now to the real issue. WPF does not calculate the ActualHeight of elements until they are measured, which it does as part of the display pass. From the RowDefinition.ActualHeight docs:

When you add or remove rows or columns, the ActualWidth for all ColumnDefinition elements and the ActualHeight of all RowDefinition elements becomes zero until Measure is called.

So if you try to get ActualHeight before WPF has called Measure, you'll get 0 or some other bad result.

Fortunately, you don't actually need to get ActualHeight: because WPF is going to size your object to the available space (because of star sizing), you can actually have the object handle its own SizeChanged event or override OnRenderSizeChanged. Depending on how your rendering works, this event handler might update the object's set of child objects (if the object is a panel- or drawing-type object) or force a re-render using InvalidateVisual (if the object draws in a more immediate-mode style e.g. by overriding OnRender).

itowlson
Using OnRender without OnRenderSizeChanged worked in my case. Thank you!
Carlo