代码分享 ScrollViewerListener 获取ScrollViewer的位置改变

WP没有办法直接获取ScrollViewer的位置,但是可以ScrollViewer通过VerticalOffset的绑定监听实现。

下面写了一个ScrollViewerListener 用于给ScrollViewer扩展一个VerticalScrollChanged事件。

 

思路是这样的:

1 首先给ScrollViewer附加2个属性VerticalOffsetProperty和ListenerProperty.

 

2 VerticalOffsetProperty是VerticalOffset的复制,但是VerticalOffsetProperty在meta里定义了自己的回调OnVerticalOffsetChanged,

然后利用Binding的特点 将Source 设置成ScrollViewer,使ta的VerticalOffset和ScrollViewerListener引用的VerticalOffsetProperty绑定起来,

这样ScrollViewer的VerticalOffset也会使VerticalOffsetProperty同时改变,并能在OnVerticalOffsetChanged回调里面处理了。

 

3 ListenerProperty就是ScrollViewerListener本身的引用。

在处理OnVerticalOffsetChanged回调的时候有个问题,就是sender是ScrollViewer怎么取到ScrollViewerListener呢?

通过ListenerProperty就可以把ScrollViewerListener附加给ScrollViewer这样就可以取得ScrollViewerListener的引用了。

也不会因为在静态方法引用了ScrollViewerListener造成GC不能回收(网上有一种在构造函数使用lambda的方法会产生这种问题)

 

4 最后取回ScrollViewerListener的引用,并引发VerticalScrollChanged事件。功能就完成了。

 

View Code
/// <summary>

 /// ScrollViewerListener

 /// </summary>

 internal class ScrollViewerListener

 {

 /// <summary>

 /// 附加ScrollViewerListener

 /// </summary>

 public static readonly DependencyProperty ListenerProperty;



 /// <summary>

 /// 附加VerticalOffset

 /// </summary>

 private static readonly DependencyProperty VerticalOffsetProperty;



 static ScrollViewerListener()

 {

 ListenerProperty = DependencyProperty.RegisterAttached("Listener", typeof (ScrollViewerListener),

 typeof (ScrollViewer),

 new PropertyMetadata(default(ScrollViewerListener)));

 VerticalOffsetProperty = DependencyProperty.RegisterAttached("VerticalOffset", typeof (double),

 typeof (ScrollViewer),

 new PropertyMetadata(default(double),

 OnVerticalOffsetChanged));

 }



 /// <summary>

 /// ScrollViewer监听器

 /// </summary>

 /// <param name="scrollViewer">ScrollViewer</param>

 public ScrollViewerListener(ScrollViewer scrollViewer)

 {

 if (scrollViewer == null) return;

 //附加ScrollViewerListener给ScrollViewer

 scrollViewer.SetValue(ListenerProperty, this);

 //附加绑定ScrollViewer.VerticalOffset给VerticalOffsetProperty

 scrollViewer.SetBinding(VerticalOffsetProperty, new Binding("VerticalOffset") { Source = scrollViewer });



 }



 private static void OnVerticalOffsetChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)

 {

 var scrollViewer = sender as ScrollViewer;

 if (scrollViewer != null && e.OldValue != e.NewValue)

 {

 //从scrollViewer取回ScrollViewerListener

 var listener = scrollViewer.GetValue(ListenerProperty) as ScrollViewerListener;

 if (listener != null)

 {

 listener.OnVerticalScrollChanged();

 }

 }

 }

 /// <summary>

 /// 纵向滚动事件

 /// </summary>

 public event EventHandler VerticalScrollChanged;



 private void OnVerticalScrollChanged()

 {

 var tmp = VerticalScrollChanged;

 if (tmp != null) 

 tmp(this, EventArgs.Empty);

 }

 }

你可能感兴趣的:(scrollview)