I would strongly recommend changing your listbox to Listview. Why?
Since ListView is inherited from ListBox you will have all features of ListBox in ListView Also.
For Windows 8.1 and above
Why would I recommed? Because ListView has ListViewPersistenceHelper Which will help you save and retrieve Relative Scroll position of ListView.
See this Example for how to implement ListViewPersistenceHelper
And for your selections, You can create a Global Variable in App.xaml.
public int ListViewScrollSelectedIndex;
which saves SelectedIndex of your ListView. When you repopulate your ListView, you can set it as
ListView.SelectedIndex = ListViewScrollSelectedIndex;
This should take care of both issues.
For WPF
If you want to get the current scroll position of your List Box, You need to gain access to its scroll viewer first.
Here is the code that will fetch you the scroll viewer.
private ScrollViewer GetObjectScrollViewer(DependencyObject dependencyObject)
{
if (dependencyObject is ScrollViewer)
return dependencyObject as ScrollViewer;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
{
var _scrollViewer = GetObjectScrollViewer(VisualTreeHelper.GetChild(dependencyObject, i));
if (_scrollViewer != null) return _scrollViewer;
}
return null;
}
ScrollViewer has a VerticalOffset which will give you vertical position of Scrollviewer. Save it to a double in a variable created in App.xaml when you are depopulating the ListBox.
var _ListBoxScrollViewer = GetObjectScrollViewer(MyListBox);
ScrollPosition = _ListBoxScrollViewer.VerticalOffset;
Now when you populate it again assign the scrollviewer's ScrollToVerticalOffset so that it can go back to same position.
var _ListBoxScrollViewer = GetObjectScrollViewer(ListBox);
if (_ListBoxScrollViewer != null) _ListBoxScrollViewer.ScrollToVerticalOffset(ScrollPosition);
Hope This Helps.