How UI Layout Works

Few days ago, I was stuck with a GUI issue where WPF controls were not getting rendered in memory. Everything was arranged properly in a Visual Tree of parent control but still somehow child was not able to draw with custom size.
So, to solve this issue I took  help of a book called WPF Control Development by Kevin Hoffman.

I thought I should share how this layout process works under the hood. So there it is:
___________________________________________________________________________
The layout system in WPF is a conversation between the layout container and its
children. This conversation takes place in two stages that are often referred to as passes.
This two-pass approach starts at the root of the visual tree and recursively traverses the
tree until all containers have been given the chance to perform the layout process with
their children.
In the first pass of the conversation, the parent asks its children how much space they
need to display themselves. The parent informs each child about the available size based
on constraints such as margin, alignment, and so on. This is the layout space allocated to
the child. Based on this layout space, the child responds to the container, indicating the
total space (remember, these are rectangles) it needs to display itself.
Programmers often cringe when they see or hear the word “recursion,” so we’ll keep this
paragraph short. This process is recursive. Before the child responds to its parent indicating
how much space it needs, it asks all of its children how much space they need. Once
all of the children respond, that information is aggregated according to the rules that are
part of that control and then passed up to the parent. This occurs when you have nested
layout controls, say a WrapPanel that contains multiple StackPanels.
At the end of the first phase, the parent determines the total size that can be allocated to
the child for its layout. This is the final size that will be assigned to the child. In the
second phase, the parent informs the child of its final size.


For example, if the size of the parent is 400x400 and its only child has a margin of
(20,20,20,20) set on it, the size passed to its MeasureOverride method will be 360x360.
The child may report a size other than 360x360 depending on its layout logic or the
layout logic of its children. This could happen if the child control decides that it doesn’t
need all the space it has been given and can lay itself out in a smaller space. Therefore,
ArrangeOverride may see a different final layout size. The significance of this fact is
subtle, but if you’re aware of it, you can save yourself some trouble. If you are precalculating
rectangles within MeasureOverride, you might have to recalculate them again within
ArrangeOverride. It is always a safer bet to never blur the responsibilities of the methods.
Make sure the measurement pass only determines required sizes and the arrangement pass
performs the actual layout. In other words, do not share any state between
MeasureOverride and ArrangeOverride.
Another thing to keep in mind is that if the child has explicitly set its own height or
width, the layout pass of the containing panel respects the explicit size.

Comments

Popular posts from this blog

Binding Previous Item's data in ItemsControl