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.
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 AtachedProperty
as 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With