Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scroll the scrollviewer to top through viewmodel

Tags:

scroll

mvvm

wpf

I am using the ScrollViewer with the MVVM pattern, and a list of items is wrapped by the ScrollViewer, such as

<ScrollViewer>
  <ListView>
    <ListView.View>
        <GridView>
            <GridViewColumn
                Header = "Name"
                DisplayMemberBinding="{Binding Path=Name}"
            />              
        </GridView>
    </ListView.View>
  </ListView>
</ScrollViewer>

The items of the listview are bound to a collection of objects in the viewmodel. I want the scrollviewer to scroll to the top whenever a item is added or removed from the collection.
I need the viewmodel to trigger the event, rather than using the ScrollToTop() method in the code-behind of the view.

like image 889
D.Young Avatar asked May 22 '11 14:05

D.Young


1 Answers

IMHO, the clearest way to do this is using a "Behavior" via an AttachedProperty. An AttachedProperty is a mechanism to extend existing controls functionality.

First, create a class to hold the AtachedProperty, for instance:

public class ScrollViewerBehavior
{
    public static bool GetAutoScrollToTop(DependencyObject obj)
    {
        return (bool)obj.GetValue(AutoScrollToTopProperty);
    }

    public static void SetAutoScrollToTop(DependencyObject obj, bool value)
    {
        obj.SetValue(AutoScrollToTopProperty, value);
    }

    public static readonly DependencyProperty AutoScrollToTopProperty =
        DependencyProperty.RegisterAttached("AutoScrollToTop", typeof(bool), typeof(ScrollViewerBehavior), new PropertyMetadata(false, (o, e) =>
            {
                var scrollViewer = o as ScrollViewer;
                if (scrollViewer == null)
                {
                    return;
                }
                if ((bool)e.NewValue)
                {
                    scrollViewer.ScrollToTop();
                    SetAutoScrollToTop(o, false);
                }
            }));
}

This attached property allows a ScrollViewer having "magically" a new property of type Boolean, acting like a DependencyProperty in your XAML. If you bind this property to a standard property in your ViewModel, for instance:

private bool _reset;
public bool Reset
{
    get { return _reset; }
    set
    {
        _reset = value;
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("Reset"));
    }
}

(again, the name is up to you) and then you set this Reset property to true, your ScrollViewer will scroll to top. I have named the AtachedPropertyas AutoScrollToTop, but the name is not important for this purpose.

The XAML will be something like:

<ScrollViewer my:ScrollViewerBehavior.AutoScrollToTop="{Binding Reset, Mode=TwoWay}">
    <ListView>
        <ListView.View>
            <GridView>
                <GridViewColumn
                    Header = "Name"
                    DisplayMemberBinding="{Binding Path=Name}"
                />
            </GridView>
        </ListView.View>
    </ListView>
</ScrollViewer>

Note: my is the namespace where your ScrollViewerBehavior class lives. For example: xmlns:my="clr-namespace:MyApp.Behaviors"

Finally, the only thing you have to do in your ViewModel is to set Reset = true when you like, in your case, when you add or remove an element from the collection.

like image 145
antiocol Avatar answered Sep 24 '22 17:09

antiocol