WPF 自訂控件可透過覆寫 OnRender(DrawingContext) 進行底層繪圖,適合高效能、大量資料視覺化場景。本文從零開始,逐步實作矩形繪製、滑鼠拖曳、裁剪邊界、動畫過渡,並對比自繪與組合控件的適用場景。
public class CustomRender : Control
{
protected override void OnRender(DrawingContext dc)
{
dc.DrawRectangle(Brushes.Bisque, null, new Rect(0, 0, 50, 50));
}
}
在 Window 中設定 Content = new CustomRender { Width=200, Height=300 } 即可看到左上角 50×50 米色矩形。DrawingContext 另支援 DrawEllipse、DrawGeometry、DrawText 等。
核心邏輯:
MouseDown:記錄起始點 _startPoint,呼叫 CaptureMouse()。MouseMove:計算位移 delta = current - _startPoint,更新矩形位置 _rect.Location += delta,呼叫 InvalidateVisual() 觸發重繪。MouseUp:釋放滑鼠捕捉 ReleaseMouseCapture()。為讓背景可見,OnRender 先繪製背景:
dc.DrawRectangle(Background, null, new Rect(RenderSize));
使用 DrawingContext.PushClip 限制繪製區域:
var clipRect = new Rect(new Point(0,0), RenderSize);
var clipGeom = new RectangleGeometry(clipRect);
clipGeom.Freeze(); // 凍結提升效能
dc.PushClip(clipGeom);
dc.DrawRectangle(Brushes.Bisque, new Pen(Brushes.Orange, 1), _rect);
dc.Pop(); // 結束裁剪範圍
Pop() 也用於結束 PushOpacityMask、PushEffect 等。搭配 GuidelineSet 可對齊裝置像素避免模糊。
拖曳結束時,讓矩形平滑移動到目標位置:
var anim = new RectAnimation(_rect, _targetRect, new Duration(TimeSpan.FromMilliseconds(600)));
dc.DrawRectangle(Brushes.Bisque, pen, _rect, anim.CreateClock());
同理可對 Color、Size 等屬性套用動畫。
OnRender 迴圈繪製。| 維度 | 自繪 | 組合控件 |
|---|---|---|
| 效能(大量元素) | 極佳 | 一般 |
| 樣式/模板支援 | 需自行實作 | 原生支援 |
| 視覺樹/邏輯樹 | 無 | 完整 |
| 事件/命令繫結 | 手工處理 | 原生 |
| 維護性/團隊協作 | 較難 | 容易 |
建議:除非遇到極高效能需求或極特殊視覺效果,優先使用組合控件(ControlTemplate、DataTemplate、Panel 組合),善用 WPF 豐富的樣式系統。
文章附上完整專案原始碼,包含 CustomRender.cs、Window1.xaml.cs,涵蓋所有上述功能,可直接下載執行體驗。