WP8中 ListBox x下拉刷新 以及 ScrollViewer/ListBox 的ManipulationCompleted 失效的解决方案

 

今天在做 Wp8  中的ListBox 下拉刷新 发现一个蛋疼的问题 ManipulationCompleted   失效 这个事件死活不会触发 。。。  

没有 MainpulationComplated 手势探测就很蛋疼了 (别告诉我用gestures的toolkit 那样做就恶心了。。。。 )

 

折腾了半天 发现 在ScrollViewer下的Border  handler 了MainpulationCompleted 事件  (不知道这个是不是 控件的bug 。。。 囧)

 

那么既然 ScrollViewer 中拿不到事件 那我就再他下面去取事件吧 。。

 

直接上代码。。 具体的解释 在代码里面, 具体的说明自己看注释把。。。 

 

 public class ScrollBehavior :Behavior<ListBox>

    {

        public event EventHandler<ScrollEventArgs> OnScroll;



        private ScrollContentPresenter _scrollContentPresenter; 



        private ScrollViewer _scrollViewer;



         



        protected override void OnAttached()

        {

            

            base.OnAttached();



            this.AssociatedObject.LayoutUpdated += (sender, e) =>

            { 

                if (_scrollContentPresenter == null)

                {
            // 获取ListBox 中的 ListBox中的 ScrollViewer 以便获取当前滚动位置 _scrollViewer
= FindChildOfType<ScrollViewer>(this.AssociatedObject, obj => { return true; }); if (_scrollViewer == null) { return; }
            //获取ScrollViewer 中的ContentPresenter 用来订阅ManipulationCompleted 事件,之所以不取Handle住事件Border 是考虑到 ScrollView 有可能被定制 里面就可能不止一个 Border
            //而ContentPresenter 是在border 下面的 事件可以正常捕获 而且 在ScrollViwer 中 ContentPresenter 是唯一的。
_scrollContentPresenter
= FindChildOfType<ScrollContentPresenter>(_scrollViewer, obj => { return true; }); if (_scrollContentPresenter != null) { Logger.LogMessage("Event handler attched");
              // 订阅事件 获取手势结束时的坐标 _scrollContentPresenter.ManipulationCompleted
+= OnManipulationCompleted;
              // 订阅事件 获取手势开始时的坐标
// 注意:这里之所以不订阅 MainpulationStart事件 是因为 该事件给出的坐标是在点击位置 所在控件中的相对坐标
// 比如手势开始时点击位置是在ListBox 中 第三个ITem 中的一个图片上 那么给出坐标是这个图片中的相对坐标而非ScrollViewer的
// 而 ManipulationCopleted 给出的坐标是ScrollViewer的相对坐标 。。 坐标系不统一很蛋疼的。 _scrollContentPresenter.MouseLeftButtonDown
+= OnMouseLeftButtonDown; } } }; base.OnAttached(); } System.Windows.Input.MouseButtonEventArgs _buttonDownArgs; void OnMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { _buttonDownArgs = e; } void OnManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e) { double delta = e.ManipulationOrigin.Y - _buttonDownArgs.GetPosition(e.ManipulationContainer).Y;/这就是通过MouseLeftButtonDown 获取到坐标的好处,直接统一了坐标系:)
       //下面就就是判断手势位置什么的了 我就不解释。。。  ScrollEventArgs 这些我自己定义的参数类 大家就不要在意啦。。。
if ( _scrollViewer.ScrollableHeight == _scrollViewer.ScrollableHeight && delta <-100) { FireOnScroll(new ScrollEventArgs(ScrollState.Bottom)); } else if (_scrollViewer.VerticalOffset ==0 && delta > 100) { FireOnScroll(new ScrollEventArgs(ScrollState.Top)); } } void FireOnScroll(ScrollEventArgs args) { if (OnScroll != null) { OnScroll(_scrollViewer, args); } } static T FindChildOfType<T>(DependencyObject root, Func<T, bool> verifyFunc) where T : class { var queue = new Queue<DependencyObject>(); queue.Enqueue(root); while (queue.Count > 0) { DependencyObject current = queue.Dequeue(); for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--) { var child = VisualTreeHelper.GetChild(current, i); var typedChild = child as T; if (typedChild != null) { if (verifyFunc(typedChild)) return typedChild; } queue.Enqueue(child); } } return null; } }

 

 

 

你可能感兴趣的:(scrollview)