ワンクリックで
wpf-rule-rendering-antipatterns
WPF rendering anti-patterns: no InvalidateVisual in loops, no resource allocation in OnRender.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
WPF rendering anti-patterns: no InvalidateVisual in loops, no resource allocation in OnRender.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
WPF IValueConverter rules: MarkupExtension singleton, pure functions, null/UnsetValue handling, TemplateBinding.
WPF Freezable performance rules: Freeze() all Brush/Pen/Geometry; create-and-freeze in constructor, reuse in OnRender.
WPF MVVM layer-separation rules: no System.Windows in ViewModels, BCL-only types, CommunityToolkit.Mvvm base classes. Preloaded into MVVM-related wpf-dev-pack agents.
Banned wpf-dev-pack patterns (P-001..P-004): ViewModelLocator, code-behind DataContext, Stateless ViewModel, mixing composition paths.
WPF ResourceDictionary rules: Generic.xaml as MergedDictionaries hub only, per-control style files, resource order.
View-ViewModel wiring for CommunityToolkit.Mvvm: Mappings.xaml + implicit DataTemplate (ViewModel First).
| name | wpf-rule-rendering-antipatterns |
| description | WPF rendering anti-patterns: no InvalidateVisual in loops, no resource allocation in OnRender. |
| user-invocable | false |
Common WPF rendering mistakes that cause performance problems or visual corruption.
Calling InvalidateVisual() inside a loop schedules a separate render pass for each iteration.
WPF does not coalesce these — each call queues a layout/render cycle, causing frame drops or freezes.
// Prohibited: InvalidateVisual inside a loop
foreach (var item in items)
{
item.Value = ComputeNewValue(item);
InvalidateVisual(); // ← queues N render passes
}
Mutate all state first, then invalidate once after the loop completes.
// Correct: one invalidation after all state is updated
foreach (var item in items)
{
item.Value = ComputeNewValue(item);
}
InvalidateVisual(); // ← single render pass
For data-driven scenarios where items notify individually, suppress notifications during bulk update and raise a single reset at the end:
// Correct: bulk update with deferred notification
_suppressNotifications = true;
try
{
foreach (var item in items)
item.Value = ComputeNewValue(item);
}
finally
{
_suppressNotifications = false;
InvalidateVisual();
}
OnRender is called on every render pass (layout changes, animations, window resize).
Allocating Brush, Pen, Geometry, or other objects inside OnRender creates garbage on every frame.
// Prohibited: resource allocation inside OnRender
protected override void OnRender(DrawingContext dc)
{
var brush = new SolidColorBrush(Colors.Red); // ← allocated every frame
var pen = new Pen(brush, 1.0); // ← allocated every frame
dc.DrawEllipse(brush, pen, _center, _rx, _ry);
}
Move resource creation to the constructor or a property setter.
See freezable-performance.md for the correct constructor-initialize-and-freeze pattern.