Explains WPF rendering pipeline (Measure/Arrange/Render passes) and hardware acceleration tiers. Use when debugging layout issues, optimizing render performance, or understanding why software rendering occurs.
View on GitHubchristian289/dotnet-with-claudecode
wpf-dev-pack
January 23, 2026
Select agents to install to:
npx add-skill https://github.com/christian289/dotnet-with-claudecode/blob/main/wpf-dev-pack/skills/rendering-wpf-architecture/SKILL.md -a claude-code --skill rendering-wpf-architectureInstallation paths:
.claude/skills/rendering-wpf-architecture/# WPF Rendering Architecture
## Rendering Pipeline Overview
```
User Input → Property Change → InvalidateXxx()
↓
┌───────────────┐
│ Measure Pass │ → Determines DesiredSize
├───────────────┤
│ Arrange Pass │ → Determines ActualSize/Position
├───────────────┤
│ Render Pass │ → OnRender() / DrawingContext
└───────────────┘
↓
Composition Tree → MILCore → DirectX → GPU
```
## 1. Layout Passes
### Invalidation Methods
| Method | Triggers | Use When |
|--------|----------|----------|
| `InvalidateMeasure()` | Measure + Arrange + Render | Size might change |
| `InvalidateArrange()` | Arrange + Render | Position might change |
| `InvalidateVisual()` | Render only | Visual appearance change |
### FrameworkPropertyMetadata Flags
```csharp
public static readonly DependencyProperty RadiusProperty =
DependencyProperty.Register("Radius", typeof(double), typeof(MyControl),
new FrameworkPropertyMetadata(10.0,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure));
```
| Flag | Effect |
|------|--------|
| `AffectsMeasure` | Triggers Measure pass |
| `AffectsArrange` | Triggers Arrange pass |
| `AffectsRender` | Triggers Render pass |
| `AffectsParentMeasure` | Parent re-measures |
| `AffectsParentArrange` | Parent re-arranges |
### Custom Control Layout
```csharp
protected override Size MeasureOverride(Size availableSize)
{
// Calculate desired size based on content
double width = Math.Min(200, availableSize.Width);
double height = Math.Min(100, availableSize.Height);
return new Size(width, height);
}
protected override Size ArrangeOverride(Size finalSize)
{
// Position children within finalSize
foreach (UIElement child in Children)
{
child.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
}
return finalSize;
}
protected override void OnRender(Dra