WPF ItemsControl Virtualization and Fast Moving Data SetsPosted: January 3, 2008
As some have commented, GUI object virtualization is an important part of WPF. It allows WPF to only create a small subset of UI element objects when binding to a much larger set of data objects. The subset usually relates to the elements visible on the screen. These UI objects can also be reused as the user scrolls through a large data set, reducing pressure on the garbage collector. This post covers a WPF sample demonstrating the behavior of the ItemsControl and looks at the possibility of using UI virtualization to optimize model/view updates for a fast moving data set.
In the finance industry data objects can be updating very quickly. It’s common to have a data set of around 3000 objects updating at over 7000 times per second. The challenge is to efficiently update the data model without impairing the user experience. Sometimes it’s possible to throttle updates to the client process through an intermediary server, but in some cases these updates need to be real-time.
One technique used when binding to a fast moving data model is to avoid sending update events if the data is not visible – i.e. there are no visible UI elements hooked up to the data. A possible way of detecting if a data object is being viewed is if the INotifyPropertyChanged PropertyChanged event has been wired up or not. If an ItemsControl is bound to a collection of data objects supporting this interface the virtualization of the UI objects will cause this event to be hooked and unhooked depending if the data is being displayed or not. In theory, a fast moving data set could simply use the status of the event on the INotifyPropertyChanged interface to test if it needs to notify the presentation tier that data has changed. Realistically, this technique needs to be used with other optimizations such as conflating and queuing the data updates. But having an effective ‘I am being observed’ flag would be really useful way of optimizing the protocol between the model and the view.
To demonstrate the behavior and test the usefulness of using this event I’ve posted a small sample application. This shows a ListBox bound to 1000 items (of type MyObject). The MyObject class contains a static property – a separate collection that represents the INotifyPropertyChanged.PropertyChanged event’s hooked status. The MyObject catches hooking and unhooking this event and updates the HookStatus collection.
The ListBox is bound to the MyObject collection so that we can test the behavior of the ItemsControl and how it hooks and unhooks the MyObject class as the virtual UI objects are created and reused. A custom ItemsControl is used to show the separate hooked status collection. This ItemsControl is bound to the HookedStatusCollection and simply shows a red pixel if the MyObject is hooked up, and an empty pixel if it’s not. The 1000 element collection is represented by the 1000 pixels across the top of the window. The project is linked below (VS2008, .NET 3.5 binary included).
As can be seen by running the application the ItemsControl is very generous when it comes to creating UI objects. It’s very easy to scroll through the ListView and hook up nearly all the observed objects. This means that using the state of this event is not a good indicator of the visibility of the data. I need to investigate a little further to see how much code is executed if an invisible UI object receives a update event from its sourced object. The overhead may be minimal, but avoiding invoking the event at all would be better.
Ideally this behavior should be configurable. In some cases it makes sense to be more conservative with UI objects, especially when the cost of keeping these objects is more than the memory that they use. If there was a way of setting guideline parameters for the maximum number of UI objects that an ItemsControl should maintain then we could optimize some lists for showing real-time data updates.