这是我对 Pavlo 答案的看法。它比从 ContentControl 派生(必须使用 ControlTemplate,将其他元素添加到可视化树,并具有大量其他不需要的功能)更高效和优雅。我也相信它更正确,因为 MeasureOverride 返回正确的所需大小。
public class SquareDecorator : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
if( Children.Count == 0 ) return base.MeasureOverride(availableSize);
if( Children.Count > 1 ) throw new ArgumentOutOfRangeException("SquareDecorator should have one child");
Children[0].Measure(availableSize);
var sideLength = Math.Max(Children[0].DesiredSize.Width, Children[0].DesiredSize.Height);
return new Size(sideLength, sideLength);
}
protected override Size ArrangeOverride(Size finalSize)
{
if( Children.Count == 0 ) return base.ArrangeOverride(finalSize);
if( Children.Count > 1 ) throw new ArgumentOutOfRangeException("SquareDecorator should have one child");
double sideLength = Math.Min(finalSize.Width, finalSize.Height);
Children[0].Arrange(new Rect(0, 0, sideLength, sideLength));
return new Size(sideLength, sideLength);
}
}
以同样的方式使用它(Button 的 Horizontal/VerticalAlignment 必须是拉伸的,但这是默认设置。另请注意,如果将 SquareDecorator 的 Horizontal/VerticalAlignment 设置为非拉伸,您可以获得有用的效果。):
<z:SquareDecorator>
<Button Content="I'm Square"/>
</z:SquareDecorator>
I would have derived from FrameworkElement, but it looks like neither Silverlight nor WinRT allow you to do that. (FrameworkElement is not sealed, but has no AddVisualChild method which makes it useless to derive from. Sigh, I hate .NET and/or Microsoft)