You can use both the RenderTransform and LayoutTransform properties to apply a transform, such as scaling or rotation, to an element and all of its children. Transforms are described in Chapter 13, but it is useful to understand their impact on layout.
If you apply a transform that doubles the size of an element, the element will appear to be twice as large on-screen. You would normally want the layout system to take this into account—if a Rectangle with a Width of 100 is scaled up to twice its size, it will normally make sense for the layout system to treat it as having an effective width of 200. However, you might sometimes want the transformation to be ignored for layout purposes. For example, if you are using a transform in a short animation designed to draw attention to a particular part of the UI, you probably don't want the entire Ul's layout to be changed as a result of that animation.
You can apply a transform to an object using either LayoutTransform or RenderTransform. The former causes the transform to be taken into account by the layout system, and the latter causes it to be ignored. Example 3-30 shows three buttons, one containing untransformed content, and the other two containing content transformed with these two properties.
Example 3-30. RenderTransform and LayoutTransform
<StackPanel> <Button> <TextBlock>
Foo bar </TextBlock> </Button> <Button> <TextBlock> <TextBlock.RenderTransform>
<ScaleTransform ScaleX="3" ScaleY="3" /> </TextBlock.RenderTransform> Foo bar </TextBlock> </Button> <Button> <TextBlock> <TextBlock.LayoutTransform>
<ScaleTransform ScaleX="3" ScaleY="3" /> </TextBlock.LayoutTransform> Foo bar </TextBlock> </Button> </StackPanel>
Figure 3-33 shows the results. As you can see, the button with content scaled by RenderTransform has the same size border as the unscaled one. The presence of the transform has had no effect on layout, and the content no longer fits inside the space allocated for it. However, the LayoutTransform has been taken into account by the layout system—the third button has been enlarged in order for the scaled content to fit.
The layout system deals with LayoutTransform in a straightforward manner for simple scaling transforms. The size allocated for the content is scaled up accordingly. But what about rotations? Figure 3-34 shows a button whose content has a LayoutTransform that rotates the content by 30 degrees. This is not a scaling transform, but notice that the button has grown to accommodate the content—it is taller than a normal button.
Figure 3-34. LayoutTransform and rotation
When it encounters a LayoutTransform, the layout system simply applies that transform to the bounding box, and makes sure that it provides enough space to hold the transformed bounding box. This can occasionally lead to surprising results. Consider the two buttons in Example 3-31.
Example 3-31. Rotation of content
<StackPanel> <Button HorizontalAlignment="Left"> <Line Stroke="Blue" Y1="30" X2="100" />
<Button HorizontalAlignment="Left"> <Line Stroke="Blue" Y1="30" X2="100"> <Line.LayoutTransform>
<RotateTransform Angle="50" /> </Line.LayoutTransform> </Line> </Button> </StackPanel>
These are shown in Figure 3-35. The top button looks as you would expect—the button is large enough to contain the graphical content. But the bottom one is rather surprising—the button appears to be taller than necessary.
This result makes sense only when you consider the bounding box—remember that the layout system decides how much space to allocate by applying the LayoutTransform to the bounding box. So let's look at it again, this time with the bounding boxes shown. Example 3-32 is a modified version of Example 3-31, with Border elements added to show the bounding box of the lines.
Example 3-32. Rotation showing bounding box
<StackPanel> <Button HorizontalAlignment="Left"> <Border BorderBrush="Black" BorderThickness="l">
<Line Stroke="Blue" Y1="30" X2="100" /> </Border>
Example 3-32. Rotation showing bounding box (continued)
<Border BorderBrush="Black" BorderThickness="l"> <Border.LayoutTransform>
<RotateTransform Angle="50" /> </Border.LayoutTransform> <Line Stroke="Blue" Y1="30" X2="100" /> </Border> </Button> </StackPanel>
In Figure 3-36, we can now see the bounding box of the content. The button on the bottom shows this bounding box with the same 50 degree rotation as has been applied to the line. This makes it clear that the button is exactly large enough to hold this rotated bounding box.
You might be wondering why WPF doesn't simply calculate a new bounding box for the transformed content instead of transforming the existing one. The reason is that calculating a new bounding box may not be possible. Some elements, such as Canvas, can declare a width and height that do not directly reflect their apparent size. The only sensible way in which the layout system can deal with such elements is to treat their logical shape as being rectangular. Using this approach of transforming the bounding box everywhere ensures consistent behavior.
Was this article helpful?
What you need to know about… Project Management Made Easy! Project management consists of more than just a large building project and can encompass small projects as well. No matter what the size of your project, you need to have some sort of project management. How you manage your project has everything to do with its outcome.