首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 自訂控件佈局系統深度解析:ScrollViewer、MeasureOverride、ArrangeOverride

     編輯:關於.NET

WPF 佈局系統雙階段機制是自訂控件正確渲染的基石。本文以可拖曳矩形控件為例,詳細剖析 ScrollViewer 內部原理、GetLayoutClip 裁剪、MeasureOverride/ArrangeOverride 協作流程,並說明 RenderSize、DesiredSize、InvalidateMeasure/Arrange 的實戰用法。

一、ScrollViewer 內部結構與遮罩原理

ScrollViewer 模板為 Grid 包含 ScrollContentPresenter 與兩個 ScrollBar。ScrollContentPresenter 將內容視為背景,透過移動位置實現捲動,可視區域外內容被裁剪。任何繼承 UIElement 的控件皆可覆寫 GetLayoutClip 自訂裁剪幾何:

protected override Geometry GetLayoutClip(Size layoutSlotSize)
    => new RectangleGeometry(new Rect(RenderSize));

二、ArrangeOverride:定位子元素座標

ScrollContentPresenter 覆寫 ArrangeOverride 將子元素座標偏移至可視區域外:

protected override Size ArrangeOverride(Size arrangeBounds)
{
    var child = GetVisualChild(0) as UIElement;
    if (child != null)
    {
        var point = new Point(-HorizontalOffset, -VerticalOffset); // 負偏移
        child.Arrange(new Rect(point, child.DesiredSize));
    }
    return arrangeBounds; // 回傳可用空間大小
}

參數 arrangeBounds 為父容器給予的可用空間,回傳值通常為控件 RenderSize。

三、MeasureOverride:計算 DesiredSize

DesiredSize(即 ActualWidth/Height 來源)由 MeasureOverride 產生。自訂控件範例:

protected override Size MeasureOverride(Size constraint)
{
    var w = Math.Max(double.IsInfinity(constraint.Width) ? RenderSize.Width : constraint.Width, 
                     _previewRect.Right);
    var h = Math.Max(double.IsInfinity(constraint.Height) ? RenderSize.Height : constraint.Height, 
                     _previewRect.Bottom);
    return new Size(w, h);
}

constraint 為父容器限制尺寸(可能為 Infinity),需自行處理。

四、Measure/Arrange 交互與通知機制

  • Measure → 更新 DesiredSize → 呼叫父容器 OnChildDesiredSizeChanged → 沿視覺樹向上觸發 InvalidateMeasure(DispatcherPriority.Render 非同步)。
  • ArrangeOverride 中避免呼叫自身 Measure,否則導致 InvalidateArrange → Measure 循環。WPF 內部以 MeasureInProgress/MeasureDirty 旗標防死循環。
  • 容器尺寸變更可覆寫 OnRenderSizeChanged 處理。

五、RenderSize 用途

  • OnRender 中繪製背景、邊界。
  • MeasureOverride 面對 Infinity 限制時,參考 RenderSize 判斷可用空間。

六、補充:自訂 ScrollBar vs 裁剪模式

模式優點缺點
自訂 ScrollBar 即時重繪大量資料僅繪製可視區,記憶體省每次捲動需重繪,CPU 佔用高
ScrollViewer 裁剪模式捲動不重繪,流暢初始載入大量資料慢、記憶體佔用大

七、Transform 輔助佈局

組合控件中善用 TranslateTransform、ScaleTransform、RotateTransform 搭配 CompositionTarget.Rendering 或動畫類別,可實現豐富動態佈局效果。

八、完整原始碼

文章附上範例專案原始碼,包含可拖曳矩形控件、支援 ScrollViewer 的自訂面板,可直接編譯運行觀察 Measure/Arrange 呼叫順序與裁剪效果。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved