A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
The behavior is caused by how WPF generates and manages UI elements and visuals for list controls, not by a leak in VirtualizingStackPanel itself.
For large item sets, WPF’s standard layout system creates a container and computes layout for each visible item. With UI virtualization enabled, WPF only creates containers and visuals for items that are on-screen, but it still may allocate short-lived objects (such as brushes and geometry/rect-like data) when visual states change, including hover highlighting.
From the WPF performance guidance:
- UI virtualization means item containers and layout are created only for visible items, but all data items are still in memory in a data-binding scenario.
-
VirtualizingStackPanelandVirtualizingPanelwork withItemsControl(such asListView,ListBox,ListView) to generate elements only for visible items and remove visuals when they scroll out of view. - Visual objects for items are generated or kept alive only while visible; when they leave the viewable area, their visuals may be removed.
This implies:
- Hovering over rows repeatedly changes the visual state of the same small set of on-screen containers, but WPF may allocate new brushes and related objects for each state transition.
- The allocations are short-lived and should be collected by Gen 0/Gen 1 GC; frequent collections are expected when many small transient objects are created.
There is no documented mechanism to “plug into” or cache the internal brushes and visuals that WPF uses for built-in hover states. The supported knobs are the ones already in use:
- Enabling UI virtualization via
VirtualizingStackPanelandItemsControl. - Using recycling mode for item containers.
The official guidance for large data sets focuses on:
- Ensuring virtualization is actually active (for example, not setting
ScrollViewer.CanContentScroll="false"and not settingVirtualizingStackPanel.IsVirtualizing="false"). - Being careful with additional state stored on item containers when using recycling, because containers are reused for different items and any state that belongs to the data item should be stored on the item, not the container.
There is no mention in the documentation of SnapsToDevicePixels or layout rounding as a cause of large allocations for hover effects, nor of a supported way to change the internal rendering pipeline for DataGridRow hover visuals.
Given the available guidance, the practical options within the documented model are:
- Keep UI virtualization and recycling enabled (which is already done).
- Avoid disabling virtualization via
CanContentScrollorIsVirtualizing. - If hover behavior is still too allocation-heavy for the scenario, define a custom row style and visual states that use simpler or shared resources under application control, accepting that this moves away from the default template but stays within the supported styling model.
There is no documented way to reduce these specific internal allocations while preserving the exact native look and feel beyond the general virtualization and control-optimization techniques.
References: