tags:

views:

53

answers:

2

I've got a ScrollViewer for a StackPannel. The users want the save the position of the ScrollViewer so when the application is re-loaded with their data the StackPannel will show the items they were viewing before. It has nothing to do with which items were selected, if any, merely the potion of the ScrollViewer in relation to the StackPannel items. So, if the StackPannel has 50 items and the ScrollViewer is scrolled so that items 20-25 of the StackPannel are visible I need to reload the application and scroll down to that position without selecting an item. Also, I'm using MVVM and I'd like to set the ScrollViewer position via the ViewModel code too.

A: 

Have you looked into using the ScrollViewer.ScrollInfo property? It has members that represent the offset of each scroll bar (HorizontalOffset, VerticalOffset) that you could try binding to. I'm not sure if those are dependency properties, though.

Another option would be to find the actual ScrollBar controls in the visual tree, and bind to the Position property of each of them.

Andy
+1  A: 

Below sample will store scroll offset in a VM and load it when window (TestWindow) opens. You should also store and load size of window since it will most likely affect scroll offset as well. If you want to you can move the code behind in TestWindow to an attached behavior class.

XAML:

<Window x:Class="ScrollTest.TestWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="TestWindow" Height="200" Width="300"
    Loaded="OnLoaded"
    Closing="OnClosing">
    <Grid>
        <ScrollViewer Name="_scroll"  VerticalScrollBarVisibility="Auto">
            <StackPanel>
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
                <Button Content="Click me" />
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Window>

Code behind:

using System;
using System.ComponentModel;

using System.Windows;


namespace ScrollTest
{
    public partial class TestWindow : Window
    {
        public TestWindow()
        {
            InitializeComponent();
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            _scroll.ScrollToVerticalOffset((DataContext as VM).ScrollOffset);
        }

        private void OnClosing(object sender, CancelEventArgs e)
        {
            (DataContext as VM).ScrollOffset = _scroll.VerticalOffset;
        }
    }

    public class VM
    {
        public double ScrollOffset { get; set; }
    }
}

Usage:

private void OnOpenOpenTestWindow(object sender, RoutedEventArgs e)
{
    TestWindow testWindow = new TestWindow();
    testWindow.DataContext = _vm;
    testWindow.Show();
}

private VM _vm = new VM();
Wallstreet Programmer