WPF 佈局系統核心在於兩階段協商:**Measure (測量)** 與 **Arrange (排列)**。自定義 Panel 必須覆寫 MeasureOverride 與 ArrangeOverride,並確保遍歷所有子元素呼叫其 Measure 與 Arrange 方法。
child.Measure(Size),回傳總需求尺寸。child.Arrange(Rect),回傳實際使用尺寸。將子元素沿對角線依次排列,每個元素右下偏移自身大小。
using System;
using System.Windows;
using System.Windows.Controls;
namespace CustomPanel {
public class DiagonalPanel : Panel {
// 測量階段:累加所有子元素寬高
protected override Size MeasureOverride(Size availableSize) {
double totalWidth = 0, totalHeight = 0;
foreach (UIElement child in Children) {
// 給子元素無限大空間讓其測量自有需求尺寸
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Size childSize = child.DesiredSize;
totalWidth += childSize.Width;
totalHeight += childSize.Height;
}
return new Size(totalWidth, totalHeight);
}
// 排列階段:依序定位
protected override Size ArrangeOverride(Size finalSize) {
Point currentPos = new Point(0, 0);
foreach (UIElement child in Children) {
Rect childRect = new Rect(currentPos, child.DesiredSize);
child.Arrange(childRect); // 實際安排位置
currentPos.Offset(childRect.Width, childRect.Height); // 對角線偏移
}
return new Size(currentPos.X, currentPos.Y);
}
}
}
<local:DiagonalPanel>
<Button Content="First" />
<Button Content="Second" />
<Button Content="Third" />
</local:DiagonalPanel>
三個按鈕將沿對角線從左上向右下依次排開。
double.PositiveInfinity:Measure 時傳遞無限大,讓子元素不受父容器限制,獲得真實 DesiredSize。DesiredSize:Measure 完成後由系統自動設定的屬性,Arrange 階段直接使用。MeasureOverride 回傳「理想需求」;ArrangeOverride 回傳「實際佔用」(通常等於 finalSize 或子元素佈局邊界)。VirtualizingPanel)。availableSize 可能為 Infinity (如 ScrollViewer 內);finalSize 可能小於需求尺寸 (需裁剪/壓縮邏輯)。IScrollInfo 實現實體化虛擬化。LayoutTransform 或 RenderTransform 產生過渡動畫。掌握 Measure/Arrange 雙階段協商,即掌握了 WPF 佈局系統的靈魂,能構建任意想像的自定義容器。