Xceed has been working for over 1.5 years and has put over 18000 person-hours of work on one single new Silverlight control, so that with only a couple of lines of code, you can achieve some magic.
A bit of history.
At Xceed, we've been creating components and class libraries for Windows developers for 16 years. Our first datagrid control was started 10 years ago. We offered a variety of other UI controls as well, such as charts, treeviews, menus, navigation and docking window controls. Like other component vendors, we created a “collection” or “suite” of many controls. Five years ago, our entire UI controls team began to focus solely on developing datagrid controls.
By putting all our energy exclusively behind datagrids, we felt we could do a better job than by spreading ourselves thin working on many controls. We could elevate datagrids to the next level, and cater to developers who would rather have a great datagrid than a collection of mediocre controls. We would target developers who value quality over quantity.
This move was made when we began developing Xceed DataGrid for WPF. It allowed Xceed to be the first to market with a datagrid for WPF (released January 2007, months to years before the other component vendors had theirs ready). We were not only first, but we had an amazing product that got impressive testimonials. Microsoft even used it in parts of Visual Studio 2010.
Our competitors kept their existing strategy of creating a wide variety of UI controls. Their datagrids received relatively little love. In contrast, with only one product type to think about, we were able to churn out an impressive 39 updates in 3.5 years. Customers were rarely kept waiting for resolutions to issues or new features. Today our WPF datagrid leads in stability and features, and offers perhaps the best user experience of any datagrid on any platform.
So what's new in the datagrid department that’s magical?
If you take a look at the competition's Silverlight datagrids and marketing for them, you'll see a recurring message: everyone claims that their datagrid is fast. "Blazing fast" says one. "The fastest" says another. Some of them are indeed fast, but in order to be fast, they have to load up the entire data source first.
That might be OK for Windows Forms applications accessing a local SQL server, however, this is
Sparta Silverlight. Many apps built with Silverlight will be accessing data sources that are somewhere else on the internet, not located on the user’s own computer or on a company’s speedy intranet. Having to wait for hundreds (or thousands) of data rows to be transferred over the internet before your datagrid is functional yields a poor user experience. It also drains server and network resources, and client memory.
Web developers have been facing this challenge for years.
To avoid having to load all the data, Web developers use a pattern called "paging". If you've ever performed a Google search, you are familiar with paging. A Google search often yields thousands or millions of results, but Google only displays the first 10, and then presents you with a paging interface, providing you with “next page” and “previous page” navigation.
Most Silverlight datagrids have adopted paging as their solution to working with remote data sources. You put them into a special “virtual” or “server” mode. That’s where things fall apart.
The fast scrollbar experience disappears, replaced with paging navigation. Clicking on “next page” does nothing until a round trip to the database is completed and the next page of results is delivered. Unlike with Google searches, this can take seconds, and meanwhile the datagrid’s user interface is frozen. These delays are frustrating and reflect upon your entire application.
There’s nothing blazing fast about it.
That might explain why no other Silverlight datagrid currently provides a demo of the datagrid accessing a remote data source. The paging or data virtualization demos all use local or randomly generated data, not data on a server somewhere on the internet.
Now wouldn’t it be great if a datagrid could feel and behave as if all the data was already loaded, even if the data was on a remote server? Using a scrollbar instead of a paging interface? Wouldn’t it be great if we didn’t have to wait every time we navigated forwards or backwards for the remote database to respond?
That’s what Xceed set out to do, and we believe we have achieved this goal. We designed and built an entirely new datagrid built from the ground up with asynchronous data virtualization in mind. We implemented a number of important advances in data virtualization and datagrid user interface behavior that all work together to make browsing and editing remote data feel almost as fast as as working with local data. None of these advances have ever been done in a datagrid up until now.
These advances are, on a high-level:
- A Fluid UI that helps mask network lag
- An intelligent background record retrieval system
- Optimized network communications
- Asynchronous editing and validation
Let’s start with the Fluid UI. A Fluid UI is an animated one, where the content it presents is given a real-world feel. When items move in a Fluid UI, they don’t jump to their new position, they animate, with physics-like motion, to their new location. Things happen smoothly.
So how does that help mask network lag? It’s all about perception. Here is the scenario with typical datagrids: the user clicks “line down” or “page down” or “next page”. The datagrid immediately launches a query for more data. When that data comes in, only then does the datagrid update its display by jumping down one line or displaying the next page. The perceived response time is that of the complete round-trip of request/response to the server.
For example, if clicking “next page” takes 1.5s to obtain and display data from the data source, then the perceived waiting time is the entire 1.5s, even if a “loading” animation is displayed somewhere on the grid’s surface to acknowledge the command.
On the other hand, with a Fluid UI, when the user clicks “line down” or “page down”, an animation to the next line or page immediately begins. This animation typically takes about 0.8s to complete. During this time, the end user sees “dummy” data rows animate into view – exactly as expected. The end-user feels that everything is responding and working as expected, even if the dummy data rows have no data in them yet. When the data arrives, it fades in smoothly.
In this scenario, even if the database query (launched at the same time as the animation starts) takes 1.5s to complete, the true perceived waiting time starts only after the animation has completed, and only if the data hasn't arrived by that time. The effective waiting time in the above example is reduced to 0.8s – half the time.
The next advance is the use of an intelligent background record retrieval system. We also call it Asynchronous Data Virtualization, but either way, it’s new in datagrids.
In order to be able to launch database queries for more rows to display without freezing the UI, the data virtualization mechanism has to work in the background. No other Silverlight datagrid does this (actually we believe no other company's datagrid on any platform does this). Without being asynchronous, when data is being accessed from the data source, all UI interaction is halted. That means users can’t click at their pace to move forward a few pages, nor change their mind and scroll in the opposite direction (until a round-trip to the server completes). It feels sluggish.
One Silverlight datagrid has implemented “background loading”, but that only works when you are loading the entire data source into the datagrid, not when getting the data in portions as needed. It also means that while the entire data source is being transferred to the datagrid, the scrollbar thumb is constantly getting smaller, moving up, and the datagrid is slow. Another datagrid has implemented "Stealth Paging" but it offers no advantages whatsoever over regular paging UI except to provide a scrollbar.
Why is Xceed’s background retrieval “intelligent”? Because we have added “passive and active pre-fetching” to the mix.
What is passive pre-fetching? When a typical data virtualizing or paging datagrid first loads up, it queries for the first page of data to display. But why stop there? We know that there are two possible navigation commands an end-user can do. The first is to scroll down or go to the next page. The second is to go to a specific page. In a typical datagrid, if the user scrolls down (or up), it is guaranteed that the end-user will be kept waiting, because the next (or previous) page of data has to be requested from the server.
Why not, when requesting data from the server, ask for a bit more data than we need to display on that first page? Why not ask for an additional few pages, if the overhead of doing so is acceptable? The result is that, when the user starts scrolling down, there is no waiting. When the buffer runs out, a new request is made for more data, again asking for more than the next page.
Active pre-fetching: the icing on the cake.
When the datagrid is idle, meaning the end-user is not performing any actions, the datagrid runs a background task that makes sure that the buffer of pages before and after the one currently being displayed is kept full. If the buffer is nearly empty, why should the datagrid just sit there doing nothing? Doing nothing means that it will be a near certainty that the buffer will run out sooner and the end-user will experience lag.
Active pre-fetching makes the datagrid work harder to preserve the illusion that all the data is actually already loaded. It helps silently query for more data so that the datagrid is more often able to display the previous or next page with absolutely no lag at all.
Optimized network communications.
We’ve also advanced the state of the art in how queries are made to the data source. This comprises 3 innovations:
1. No discovery required: Unlike other data virtualized datagrids, this datagrid does not require knowing the total row count, number and size of groups, or any other information about the data source. This eliminates a sizeable extra query that all other datagrids that support data virtualization require, making the Xceed datagrid load faster than any other.
2. Optimized navigation: The datagrid requests data from the data source using relative queries instead of absolute index-based queries. Such queries execute faster on the server so navigating through the datagrid is snappier. We know of no other datagrid that works this way.
3. Query grouping and throttling: During scrolling, queries to the server for more data rows are grouped together when possible. This works because queries are asynchronous and are typically obtaining data not currently in view. During heavy scrolling, queries that are no longer needed are cancelled, thereby reducing the load on the server as well as the datagrid’s own CPU use.
So to conclude, I’ve talked about 7 techniques (Fluid UI, background data virtualization, passive and active pre-fetching, and three query optimizations) that we’ve applied to the datagrid’s data virtualization that all aim to make our Silverlight datagrid the only one to provide seemingly lightning fast access to remote data. Or put another way, it lets end-users access remote data as fast as local.
For a description of what is actually happening under the hood, see Jenny's blog post.