• 代码分享 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);
     }
     }
  • 相关阅读:
    failed to create pid file /var/run/rsyncd.pid: File exists报错
    Ansible系列之roles使用说明
    设置build.gradle打包时自动加时间
    Oracle客户端连接数据库配置
    Gradle实现自动打包,签名,自定义apk文件名
    linux定时任务执行没结果,手动执行有结果问题总结
    实现TableLayout布局下循环取出TableRow控件中的文字内容到list集合
    ImageView的src和background的区别
    关于Merge的整理--Merge的使用方法和注意事项的Demo
    关于Merge的整理--AndroidScreenSlidePager开源库中用到的
  • 原文地址:https://www.cnblogs.com/kiminozo/p/2552837.html
Copyright © 2020-2023  润新知