Optimizing performance: Controls
Windows Presentation Foundation (WPF) includes many of the common user-interface (UI) components that are used in most Windows applications. This topic contains techniques for improving the performance of your UI.
Displaying large data sets
WPF controls such as the ListView and ComboBox are used to display lists of items in an application. If the list to display is large, the application's performance can be affected. This is because the standard layout system creates a layout container for each item associated with the list control, and computes its layout size and position. Typically, you do not have to display all the items at the same time; instead you display a subset, and the user scrolls through the list. In this case, it makes sense to use UI virtualization, which means the item container generation and associated layout computation for an item is deferred until the item is visible.
UI Virtualization is an important aspect of list controls. UI virtualization should not be confused with data virtualization. UI virtualization stores only visible items in memory but in a data-binding scenario stores the entire data structure in memory. In contrast, data virtualization stores only the data items that are visible on the screen in memory.
By default, UI virtualization is enabled for the ListView and ListBox controls when their list items are bound to data. TreeView virtualization can be enabled by setting the VirtualizingStackPanel.IsVirtualizing attached property to
true. If you want to enable UI virtualization for custom controls that derive from ItemsControl or existing item controls that use the StackPanel class, such as ComboBox, you can set the ItemsPanel to VirtualizingStackPanel and set IsVirtualizing to
true. Unfortunately, you can disable UI virtualization for these controls without realizing it. The following is a list of conditions that disable UI virtualization.
Item containers in the ItemsControl are of different types. For example, a Menu that uses Separator objects cannot implement item recycling because the Menu contains objects of type Separator and MenuItem.
Setting CanContentScroll to
Setting IsVirtualizing to
An important consideration when you virtualize item containers is whether you have additional state information associated with an item container that belongs with the item. In this case, you must save the additional state. For example, you might have an item contained in an Expander control and the IsExpanded state is bound to the item's container, and not to the item itself. When the container is reused for a new item, the current value of IsExpanded is used for the new item. In addition, the old item loses the correct IsExpanded value.
Currently, no WPF controls offer built-in support for data virtualization.
An optimization to UI virtualization added in the .NET Framework 3.5 SP1 for controls that inherit from ItemsControl is container recycling, which can also improve scrolling performance. When an ItemsControl that uses UI virtualization is populated, it creates an item container for each item that scrolls into view and destroys the item container for each item that scrolls out of view. Container recycling enables the control to reuse the existing item containers for different data items, so that item containers are not constantly created and destroyed as the user scrolls the ItemsControl. You can choose to enable item recycling by setting the VirtualizationMode attached property to Recycling.
Supporting bidirectional virtualization
VirtualizingStackPanel offers built-in support for UI virtualization in one direction, either horizontally or vertically. If you want to use bidirectional virtualization for your controls, you must implement a custom panel that extends the VirtualizingStackPanel class. The VirtualizingStackPanel class exposes virtual methods such as OnViewportSizeChanged, LineUp, PageUp, and MouseWheelUp.These virtual methods enable you to detect a change in the visible part of a list and handle it accordingly.
The visual tree contains all the visual elements in an application. In addition to the objects directly created, it also contains objects due to template expansion. For example, when you create a Button, you also get ClassicBorderDecorator and ContentPresenter objects in the visual tree. If you haven't optimized your control templates, you may be creating a lot of extra unnecessary objects in the visual tree. For more information on the visual tree, see WPF Graphics Rendering Overview.
By default, when the user drags the thumb on a scrollbar, the content view continuously updates. If scrolling is slow in your control, consider using deferred scrolling. In deferred scrolling, the content is updated only when the user releases the thumb.
To implement deferred scrolling, set the IsDeferredScrollingEnabled property to
true. IsDeferredScrollingEnabled is an attached property and can be set on ScrollViewer and any control that has a ScrollViewer in its control template.
Controls that implement performance features
The following table lists the common controls for displaying data and their support of performance features. See the previous sections for information on how to enable these features.
|Control||Virtualization||Container recycling||Deferred scrolling|
|ComboBox||Can be enabled||Can be enabled||Can be enabled|
|ContextMenu||Can be enabled||Can be enabled||Can be enabled|
|DocumentViewer||Not available||Not available||Can be enabled|
|ListBox||Default||Can be enabled||Can be enabled|
|ListView||Default||Can be enabled||Can be enabled|
|TreeView||Can be enabled||Can be enabled||Can be enabled|
|ToolBar||Not available||Not available||Can be enabled|