virtualizing-wpf-ui

SKILL.md

WPF UI Virtualization

Quick Setup

<ListBox ItemsSource="{Binding LargeCollection}"
         VirtualizingPanel.IsVirtualizing="True"
         VirtualizingPanel.VirtualizationMode="Recycling"
         VirtualizingPanel.ScrollUnit="Pixel"
         VirtualizingPanel.CacheLength="2,2"
         VirtualizingPanel.CacheLengthUnit="Page"/>

Key Properties

Property Recommended Purpose
IsVirtualizing True Enable virtualization
VirtualizationMode Recycling Reuse containers
ScrollUnit Pixel Smooth scrolling
CacheLength "1,1" to "2,2" Buffer pages

Virtualization Breakers

These disable virtualization:

<!-- ❌ ScrollViewer wrapper -->
<ScrollViewer>
    <ListBox/>
</ScrollViewer>

<!-- ❌ CanContentScroll disabled -->
<ListBox ScrollViewer.CanContentScroll="False"/>

<!-- ❌ Grouping without flag -->
<ListBox>
    <ListBox.GroupStyle>...</ListBox.GroupStyle>
</ListBox>

Fixes:

<!-- ✅ No wrapper needed - ListBox has built-in ScrollViewer -->
<ListBox ItemsSource="{Binding Items}"/>

<!-- ✅ Grouping with virtualization -->
<ListBox VirtualizingPanel.IsVirtualizingWhenGrouping="True">
    <ListBox.GroupStyle>...</ListBox.GroupStyle>
</ListBox>

Recycling Mode Considerations

// When using Recycling mode, clean up in PrepareContainerForItemOverride
protected override void PrepareContainerForItemOverride(
    DependencyObject element, object item)
{
    base.PrepareContainerForItemOverride(element, item);

    var container = (ListBoxItem)element;
    // Reset any manually attached handlers or state
}

Performance Tips

Deferred Scrolling

<!-- Faster scrollbar dragging -->
<ListBox ScrollViewer.IsDeferredScrollingEnabled="True"/>

Diagnostic Check

public static bool IsVirtualizing(ItemsControl control)
{
    var panel = FindVisualChild<VirtualizingStackPanel>(control);
    return panel != null && VirtualizingPanel.GetIsVirtualizing(control);
}

public static int GetRealizedCount(ItemsControl control)
{
    var generator = control.ItemContainerGenerator;
    return Enumerable.Range(0, control.Items.Count)
        .Count(i => generator.ContainerFromIndex(i) != null);
}

DataGrid Virtualization

<DataGrid ItemsSource="{Binding Items}"
          EnableRowVirtualization="True"
          EnableColumnVirtualization="True"
          VirtualizingPanel.IsVirtualizing="True"
          VirtualizingPanel.VirtualizationMode="Recycling"/>
Weekly Installs
4
GitHub Stars
16
First Seen
Feb 28, 2026
Installed on
opencode4
gemini-cli4
github-copilot4
codex4
kimi-cli4
amp4