0

I have a DataGrid with around 500 rows. If I am scrolled down to let's row no. 200 and a new row is added to the top (beginning of the collection) it automatically scrolls up to the first row so I have to scroll down again manually. How can I prevent this to happen?

Here is a sample app to illustrate the problem:

MainWindow.xaml.cs:

using System.Collections.ObjectModel;
using System.Windows;


namespace Testnamespace
{
    public class TestClass
    {
        private int price;
        private int qty;

        public int Price { get => price; set => price = value; }
        public int Qty { get => qty; set => qty = value; }

        public TestClass(int price,int qty)
        {
            this.Price = price;
            this.Qty = qty;
        }
    }
    public partial class MainWindow : Window
    {
        private ObservableCollection<TestClass> data = new ObservableCollection<TestClass>() { new TestClass(3, 1), new TestClass(2, 1), new TestClass(1, 1) };
        public ObservableCollection<TestClass> Data { get => data; set => data = value; }
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        private void InsertButton_Click(object sender, RoutedEventArgs e)
        {
            Data.Insert(0, new TestClass(Data.Count, 1));
        }
    }
}

XAML:

<Window x:Class="Testnamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Testnamespace"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="200">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="80"/>
            <RowDefinition MinHeight="80"/>
        </Grid.RowDefinitions>
        <Button x:Name="InsertButton" Content="Insert(0)" Click="InsertButton_Click" Grid.Column="0" Height="20" Width="50" Background="Red"/>
        <DataGrid x:Name="dataGrid"
                  Grid.Row="1"
                  AutoGenerateColumns="False"
                  ItemsSource="{Binding Data, IsAsync=True}"
                  MaxWidth="800"
                  MaxHeight="1600"
                  Width="100"
                  Height="100"
                  >

            <DataGrid.Columns>
                <DataGridTextColumn Header="Price" Binding="{Binding Price}">
                </DataGridTextColumn>

                <DataGridTextColumn Header="Qty" Binding="{Binding Qty}">
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

This is how the app looks like: enter image description here

Let's say you want to keep your eyes on price=1 to see if Qty has changed but in the meanwhile new rows are added (by clicking the Insert(0) button). In this case you lose focus because it keeps scrolling up, so you have to scroll down manually. How can I prevent this to happen?

  • If this happens, you are doing something wrong when you add the item to the source collection. It sounds like you are raising a `CollectionChanged` event with an `Action` of `NotifyCollectionChangedAction.Reset`. Use the `Insert` method on the `ObservableCollection` and you should be fine. – mm8 Feb 08 '21 at 21:57
  • I am amending an ObservableCollection like this: this.Data.Insert(0, priceLadderRowData); –  Feb 08 '21 at 22:18
  • see this link : https://stackoverflow.com/questions/2064848/wpf-datagrid-how-do-i-stop-auto-scrolling-when-a-cell-is-clicked – Meysam Asadi Feb 09 '21 at 06:36
  • @RLaszlo: Then the scroll position shouldn't be reset. Please provide an example of your issue. – mm8 Feb 09 '21 at 16:26
  • @mm8 I have updated my question. I hope it clarifies my issue. –  Feb 10 '21 at 11:58

1 Answers1

0

You could manually scroll another 18.96 DIP, which is the default Height of a DataGridRow:

private void InsertButton_Click(object sender, RoutedEventArgs e)
{
    ScrollViewer scrollViewer = FindVisualChild<ScrollViewer>(dataGrid);
    double offset = scrollViewer.VerticalOffset;
    Data.Insert(0, new TestClass(Data.Count, 1));
    if (offset > 0)
        scrollViewer.ScrollToVerticalOffset(offset + 18.96);

}

private static T FindVisualChild<T>(Visual visual) where T : Visual
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
    {
        Visual child = (Visual)VisualTreeHelper.GetChild(visual, i);
        if (child != null)
        {
            T correctlyTyped = child as T;
            if (correctlyTyped != null)
                return correctlyTyped;

            T descendent = FindVisualChild<T>(child);
            if (descendent != null)
                return descendent;
        }
    }
    return null;
}
mm8
  • 163,881
  • 10
  • 57
  • 88