Matthew, as you pointed out ActualWidth
and ActualHeight
don't change if you apply transforms. ActualWidth
and ActualHeight
represent the calculated width/height after the layout system has finished calculating the size of a control (based on values such as Margin
, HorizontalAlignment
, etc.)
One way to get the size of a control taking into account all of the scale transformations that have been applied to it is to walk up the visual tree and apply all scale transforms to the ActualWidth
and ActualHeight
of a control:
public static Size GetActualSize(FrameworkElement control)
{
Size startSize = new Size(control.ActualWidth, control.ActualHeight);
// go up parent tree until reaching root
var parent = LogicalTreeHelper.GetParent(control);
while(parent != null && parent as FrameworkElement != null && parent.GetType() != typeof(Window))
{
// try to find a scale transform
FrameworkElement fp = parent as FrameworkElement;
ScaleTransform scale = FindScaleTransform(fp.RenderTransform);
if(scale != null)
{
startSize.Width *= scale.ScaleX;
startSize.Height *= scale.ScaleY;
}
parent = LogicalTreeHelper.GetParent(parent);
}
// return new size
return startSize;
}
public static ScaleTransform FindScaleTransform(Transform hayStack)
{
if(hayStack is ScaleTransform)
{
return (ScaleTransform) hayStack;
}
if(hayStack is TransformGroup)
{
TransformGroup group = hayStack as TransformGroup;
foreach (var child in group.Children)
{
if(child is ScaleTransform)
{
return (ScaleTransform) child;
}
}
}
return null;
}
Keep in mind that this might be inefficient if your visual tree is deep or you perform this many times. In practice I've never run into any problems with this, however.