これが私のバージョンの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);
}
}
同じように使用します(ボタンのHorizontal / VerticalAlignmentはストレッチする必要がありますが、これがデフォルトです。また、SquareDecoratorのHorizontal / VerticalAlignmentを非ストレッチに設定すると便利な効果が得られることに注意してください。):
<z:SquareDecorator>
<Button Content="I'm Square"/>
</z:SquareDecorator>
FrameworkElementから派生したはずですが、SilverlightもWinRTもそれを許可していないようです。(FrameworkElementは封印されていませんが、派生するのに役に立たないAddVisualChildメソッドがありません。ため息、私は.NETやMicrosoftが嫌いです)