I have TabControl that has a DataGrid inside each TabItem. It's all populated via binding. I use the row details expansion functionality, so have set the VirtualizingPanel ScrollUnit to Pixel, so scrolling is a bit more natural. 
When changing between TabItems I have row selection behaving correctly. However, setting the vertical offset on the DataGrid's ScrollViewer so it is in the exact same position as it was when you left the TabItem is not working correctly.
The way it works at the moment is, I have a behavior class on the DataGrid. On a Scrollviewer ScrollChangedEvent it saves the VerticalOffset. Upon changing to a new TabItem and changing back to the original TabItem, in the DataGrid's DataContextChanged event I set the ScrollViewer's VerticalOffset to the saved VerticalOffset.
public class DataGridBehaviors : Behavior<DataGrid>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.DataContextChanged += DataGrid_DataContextChanged;
        this.AssociatedObject.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(DataGridScrollViewer_ScrollChanged));
    }
    protected override void OnDetaching()
    {
        Console.WriteLine("OnDetaching");
        this.AssociatedObject.RemoveHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(DataGridScrollViewer_ScrollChanged));
        this.AssociatedObject.DataContextChanged -= DataGrid_DataContextChanged;
        base.OnDetaching();
    }
    private void DataGrid_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        ModuleGeometry oldModuleGeometry = (ModuleGeometry)e.OldValue;
        ModuleGeometry newModuleGeometry = (ModuleGeometry)e.NewValue;
        ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(this.AssociatedObject);
        if (scrollViewer != null)
        {
            scrollViewer.ScrollToVerticalOffset(newModuleGeometry.VerticalScrollPosition);
        }
    }
    private void DataGridScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        ModuleGeometry modGeom = (ModuleGeometry)this.AssociatedObject.DataContext;
        modGeom.VerticalScrollPosition = e.VerticalOffset;
    }
    private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
    {
        T child = default(T);
        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T;
            if (child == null)
            {
                child = GetVisualChild<T>(v);
            }
            if (child != null)
            {
                break;
            }
        }
        return child;
    }
}
What is happening is you scroll down and the top DataGridRow is partially displayed (You only see half of it). Then when you toggle between two TabItems, the program sets the VerticalOffset correctly, but then it resets again automatically to the top of the partially displayed row (showing it fully).
Before toggling. Saves VertcialOffset to 4327.2
After toggling back to the original TabItem Sets VerticalOffset to 4327.2, then for some reason and somehow automatically resets VerticalOffset to 4321.5, which is the top of the 'previously' partially visible row 

It gets even weirder when you have an expanded row loaded in the VirtualizingPanel, the jump is more dramatic.
Before toggling
After toggling back to the original TabItem

I would like to see the scroll position in exactly the same spot as when I left it, how can I accomplish this?