Reputation: 12804
I'm working on a custom WPF Panel
that works similar to a Canvas
except that the placements of its children are expressed as percentages instead of absolute offsets. The Panel
, which I'm calling PercentageCanvas
would be used like so:
<Window>
<local:PercentageCanvas>
<ChildElement local:PercentageCanvas.Left=".30" local:PercentageCanvas.Top=".50" />
<ChildElement local:PercentageCanvas.Left="0" local:PercentageCanvas.Top=".9" />
... etc ...
</local:PercentageCanvas>
</Window>
I have the PercentageCanvas
working, although not quite as I expected. The children of the PercentageCanvas
are positioned relative to the center of the child, rather than the top-left edge, as I had expected. Here's the ArrangeOverride
method I use that gives me this behavior:
protected override Size ArrangeOverride(Size finalSize)
{
int currentIndex = 0;
for (int index = InternalChildren.Count - 1; index >= 0; index--)
{
Rect rect = new Rect(finalSize);
rect.Location = new Point()
{
X = finalSize.Width * PercentagePanel.GetLeft(InternalChildren[index]) - finalSize.Width / 2,
Y = finalSize.Height * PercentagePanel.GetTop(InternalChildren[index]) - finalSize.Height / 2
};
InternalChildren[index].Arrange(rect);
currentIndex++;
}
return finalSize;
}
It seems that to counteract this center-positioning behavior, I'll need to know each child's dimensions and compensate for the child's size while computing the Location
of the Rect
. However, I don't seem to have access to the child's size in order to compute the appropriate offset.
How can I take into account the size of a Panel's child while computing the child's layout in the ArrangeOverride
method?
Upvotes: 0
Views: 81
Reputation: 12804
Found the answer while in the middle of writing up the question. All UIElements
have a DesiredSize
property which gives me exactly what I'm looking for. My ArrangeOverride
method now looks like this (you'll have to scroll to the right to see the difference):
protected override Size ArrangeOverride(Size finalSize)
{
int currentIndex = 0;
for (int index = InternalChildren.Count - 1; index >= 0; index--)
{
Rect rect = new Rect(finalSize);
rect.Location = new Point()
{
X = finalSize.Width * PercentagePanel.GetLeft(InternalChildren[index]) - finalSize.Width / 2 + (InternalChildren[index].DesiredSize.Width / 2),
Y = finalSize.Height * PercentagePanel.GetTop(InternalChildren[index]) - finalSize.Height / 2 + (InternalChildren[index].DesiredSize.Height / 2)
};
InternalChildren[index].Arrange(rect);
currentIndex++;
}
return finalSize;
}
The elements now position themselves relative to their top-left corner instead of their center.
Upvotes: 1