Using the right controls for performance

As we mentioned previouslythere are usually several different ways of achieving the same functionality, or UI display, when using WPF. Some ways will provide better performance than others. For example, we learned how some panels do more intensive layout work and, therefore, consume more CPU cycles and/or RAM than others.

Therefore, this is one area that we can investigate in order to make performance improvements. If we do not require the complex layout and resizing abilities of a Grid panel, then we can gain a performance improvement by utilizing a more efficient StackPanel or Canvas panel instead.

Another example could be that if we do not require the ability to select in a collection control, then we should use an ItemsControl element instead of a ListBox. While swapping one control will not make much of a performance improvement on its own, making this same swap in the DataTemplate of an item that will be displayed thousands of times will make a noticeable difference.

As we discovered in Chapter 5, Using the Right Controls for the Job, each time a UI element is rendered, the layout system must complete two passes, a measure pass and an arrange pass, which is collectively known as a layout pass. If the element has children and/or grandchildren, they will all need to complete the layout pass too. This process is intensive and the fewer passes that can be made, the quicker our Views will render.

As mentioned earlier, we need to be careful to ensure that we do not unnecessarily trigger additional passes of the layout system, as this can lead to poor performance. This can occur when adding or removing items to or from a panel, applying transforms on the elements, or by calling the UIElement.UpdateLayout method, which forces a new layout pass.

Because of the way that changes to a UI element will invalidate its children and force a new layout pass, we need to be especially careful when building hierarchical data in code. If we create the child elements first, then their parent objects, and then the parents of those objects, and so on, we will incur a huge performance hit, due to the existing child items being forced to perform multiple layout passes.

In order to address this issue, we need to always ensure that we build our tree from the top-down, rather than the top-up method just described. If we add the parent element(s) first, then add their children and their children if any, we can avoid the additional layout passes. The performance improvement of using the top-down method is approximately five times quicker to render, and so is not insignificant. Let's take a look at some further control-related performance benefits that we can employ next.