WPF DataGrid - How to stay focused on the bottom of the DataGrid as new rows are added?

11,428

Solution 1

Looks like DataGrid.ScrollIntoView(<item>) will keep the focus on the bottom of the DataGrid.

Solution 2

This is a simple approach using LoadingRow event:

void dataGrid_LoadingRow(object sender, System.Windows.Controls.DataGridRowEventArgs e)
{
    dataGrid.ScrollIntoView(e.Row.Item);
}

Just remember to disable it after the grid loading is finished.

Solution 3

I've found that the most useful time to call the ScrollIntoView method is from the ScrollViewer.ScrollChanged attached event. This can be set in XAML as follows:

<DataGrid
...
ScrollViewer.ScrollChanged="control_ScrollChanged">

The ScrollChangedEventArgs object has various properties that can be helpful for computing layout and scroll position (Extent, Offset, Viewport). Note that these are typically measured in numbers of rows/columns when using the default DataGrid virtualization settings.

Here's an example implementation that keeps the bottom item in view as new items are added to the DataGrid, unless the user moves the scrollbar to view items higher up in the grid.

    private void control_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        // If the entire contents fit on the screen, ignore this event
        if (e.ExtentHeight < e.ViewportHeight)
            return;

        // If no items are available to display, ignore this event
        if (this.Items.Count <= 0)
            return;

        // If the ExtentHeight and ViewportHeight haven't changed, ignore this event
        if (e.ExtentHeightChange == 0.0 && e.ViewportHeightChange == 0.0)
            return;

        // If we were close to the bottom when a new item appeared,
        // scroll the new item into view.  We pick a threshold of 5
        // items since issues were seen when resizing the window with
        // smaller threshold values.
        var oldExtentHeight = e.ExtentHeight - e.ExtentHeightChange;
        var oldVerticalOffset = e.VerticalOffset - e.VerticalChange;
        var oldViewportHeight = e.ViewportHeight - e.ViewportHeightChange;
        if (oldVerticalOffset + oldViewportHeight + 5 >= oldExtentHeight)
            this.ScrollIntoView(this.Items[this.Items.Count - 1]);
    }
Share:
11,428
Taylor Leese
Author by

Taylor Leese

I herd cats and make services scale -- sometimes at the same time.

Updated on June 09, 2022

Comments

  • Taylor Leese
    Taylor Leese almost 2 years

    I am using DataGrid from the WPF Toolkit and I need to be able to maintain focus on the bottom of the grid (i.e. the last row). The problem I'm having right now is that as rows are added the scrollbar for the DataGrid doesn't scroll along with the new rows being added. What's the best way to accomplish this?

  • joe
    joe over 14 years
    Where do you call this method?
  • Vinzz
    Vinzz over 14 years
    it does. Just make a call after you have updated your datasource with the new element. Be sure to call UpdateLayout() before ScrollIntoView though!
  • Taylor Leese
    Taylor Leese over 14 years
    Why do you need to call UpdateLayout() first? I didn't have to do that. Is it just a best practice for some reason?