views:

1532

answers:

4

I'm using a DataGrid in my silverlight application to display some data that's refreshed on a timer. My problem is that when this happens the vertical scrollbar in the grid resets to the top, whereas I want it to stay in the same position. Does anyone know how I can make this happen?

I've tried overriding the ItemsSource property on the grid to store the vertical scroll position and then reset it, but this only affects the scrollbar and doesn't force the correct rows to be displayed. Is there a way to force this behaviour?

A: 

You could try setting the SelectedItem thro the UI thread, so that the UI can refresh itself, like so

private void Button_Click(object sender, RoutedEventArgs e)
    {
        Person p = new Person() { Name="sss",Age=11};  //datagird's itemsSource is Collection<person>
        people.Add(p);
        dg.SelectedItem = p;  //dg is my datagrid name
        Dispatcher.BeginInvoke(() => { dg.SelectedItem = p; });
    }

Im assuming that new rows are loaded thro the ViewModel, so thats why it makes sense to place the BeginInvoke there. Since the ViewModel operations run on a different thread, and just setting the SelectedItem on its own might not work, this has worked for someone else

Neil
+1  A: 

Here is a similar question about Setting the scroll bar position on a ListBox

http://stackoverflow.com/questions/1842984/after-rebinding-silverlight-listbox-control-how-do-you-get-it-listbox-to-scroll-t/1845137#1845137

Since the DataGrid also supports a ScrollIntoView method, you should be able to use a similar technique such as

theDataGrid.ItemsSource = data; 
theDataGrid.UpdateLayout(); 
theDataGrid.ScrollIntoView(theDataGrid.SelectedItem, theDataGrid.Columns[0]);
Jacob Adams
A: 

I've also had issues with this. I solved it by remembering the item I want to scroll to, then re-binding the DataGrid. I handle the LayoutUpdated event in order to implement the desired functionality:

void MyDataGrid_LayoutUpdated(object sender, EventArgs e)
    {
        // Reference the data item in the list you want to scroll to.
        object dataItem = yourDataItem;

        // Make sure the item is not null and didn't already scroll to the item.
        if (dataItem != null && this.dataItemScrolledTo != dataItem)
        {
            // Remember the item scrolled to.
            this.dataItemScrolledTo = dataItem;

            // Scroll datagrid to the desired item.
            MyDataGrid.ScrollIntoView(dataItem, MyDataGrid.Columns[0]);
        }
    }
CodeMaster
+1  A: 

I couldn't find a decent answer last time I looked. I wanted to keep the current element selected in the grid but that wouldn't work on an ICollectionView refresh (I use MVVM and get automatic updates from the server).

ScrollIntoView() was not an option for me because the currently selected item may NOT be in view. Having the CurrentChanged event firing out of control was also quite a bother.

In the end, I used the Infragistics grid and it does just that out of the box. Problem solved for me.

You may have a look at the DevExpress free grid. I think it had the same nice behaviour (I tested it but I can't remember the outcome).

R4cOON