Resolving DataGrid vertical scroll bar thumb issue: updating its position and size when hiding rows or changing row heights

Microsoft’s Silverlight DataGrid control is highly optimized and has virtualization features enabled by default. But in order to achieve this level of performance several trade-offs needed to be accepted. A few of them seem to be related to the way the internal vertical scroll bar of the control works: it needs to make multiple assumptions about the invisible data amount, such as counting and estimating the height of the rows that are not currently visible in the view. This generates an issue (theoretically acceptable) with the scroll bar thumb position and its size when the rows (visible or invisible) would get different heights or become hidden (their Visibility value being set to visible or collapsed by a Binding for example).

An inacceptable issue occurs when row height or visibility status get changed and reversed at runtime: sometimes the scroll bar thumb position and size are properties are not computed to the same values as before after such an operation and its reverse. Moreover, if you get a reference to the actual vertical ScrollBar instance, you may also notice that after a while and several row operations, its Value property would report incorrectly, and this doesn’t get better even when the end user moves the scroll thumb: the Value may remain “frozen” although the grid actually scrolls content. Some people have also detected similar situations when changing the DataGrid height (such as upon a resize operation).

The best workaround found on the Web on this issue on Silverlight is to call UpdateLayout (or InvalidateMeasure) on the scroll bar or DataGrid instance. This doesn’t resolve the situation in all cases, tough.

However, very recently, digging on a similar issue, one of our customers have found a better workaround for (at least some of) these issues, and I believe it worth mentioning it: whenever you update row heights or visibility, also add a temporary column to the DataGrid.Columns collection, and then immediately remove it. (Testing further, I found out that this shouldn’t be done – so make an exception – when there are no rows already added in the grid, otherwise the control may incorrectly display the first row you add afterwards).

The final, combined workaround code should be similar to this (run the UpdateGridScroll method it whenever your rows change heights or visibility state):

private DataGridTextColumn temporaryColumn =
    new DataGridTextColumn {
        IsReadOnly = true,
        Binding = new Binding { Mode = BindingMode.OneTime } };

private void UpdateGridScroll()
{
    if (myDataGrid.Items.Count > 0)
    {
        int columnCount = myDataGrid.Columns.Count;
        if (columnCount > 0)
        {
            myDataGrid.Columns.Add(temporaryColumn);
            myDataGrid.Columns.RemoveAt(columnCount);
        }
    }
    myDataGrid.InvalidateMeasure();
}

About Sorin Dolha

My passion is software development, but I also like physics.
This entry was posted in Computers and Internet and tagged , , , , , . Bookmark the permalink.

One Response to Resolving DataGrid vertical scroll bar thumb issue: updating its position and size when hiding rows or changing row heights

  1. Chris says:

    Thank you so much for sharing! This resolved the problem for me.

Add a reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s