void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
        {
            if (_animatable == null && e.ShouldAnimate)
            {
                _animatable = new Animatable();
            }

            ScrollToPosition position = e.Position;
            double           x        = e.ScrollX;
            double           y        = e.ScrollY;

            if (e.Mode == ScrollToMode.Element)
            {
                Point itemPosition = Controller.GetScrollPositionForElement(e.Element as VisualElement, e.Position);
                x = itemPosition.X;
                y = itemPosition.Y;
            }

            if (Control.VerticalOffset == y && Control.HorizontalOffset == x)
            {
                return;
            }

            if (e.ShouldAnimate)
            {
                var animation = new Animation(v => { UpdateScrollOffset(GetDistance(Control.ViewportWidth, x, v), GetDistance(Control.ViewportHeight, y, v)); });

                animation.Commit(_animatable, "ScrollTo", length: 500, easing: Easing.CubicInOut, finished: (v, d) =>
                {
                    UpdateScrollOffset(x, y);
                    Controller.SendScrollFinished();
                });
            }
            else
            {
                UpdateScrollOffset(x, y);
                Controller.SendScrollFinished();
            }
        }
Beispiel #2
0
        void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
        {
            if (_animatable == null && e.ShouldAnimate)
            {
                _animatable = new Animatable();
            }

            if (_viewport == null)
            {
                // Making sure we're actually loaded
                if (VisualTreeHelper.GetChildrenCount(_listBox) == 0)
                {
                    RoutedEventHandler handler = null;
                    handler = (o, args) =>
                    {
                        Control.Loaded -= handler;
                        OnScrollToRequested(sender, e);
                    };
                    Control.Loaded += handler;

                    return;
                }
                _viewport = (ViewportControl)VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(_listBox, 0), 0), 0);
                if (_viewport.Viewport.Bottom == 0)
                {
                    EventHandler <ViewportChangedEventArgs> viewportChanged = null;
                    viewportChanged = (o, args) =>
                    {
                        if (_viewport.Viewport.Bottom == 0)
                        {
                            return;
                        }

                        _viewport.ViewportChanged -= viewportChanged;
                        OnScrollToRequested(sender, e);
                    };
                    _viewport.ViewportChanged += viewportChanged;
                    return;
                }
            }

            double y                  = 0;
            double targetHeight       = 0;
            double targetHeaderHeight = 0;

            var templateReusables = new Dictionary <System.Windows.DataTemplate, FrameworkElement>();

            var found = false;

            if (Element.IsGroupingEnabled)
            {
                for (var g = 0; g < Element.TemplatedItems.Count; g++)
                {
                    if (found)
                    {
                        break;
                    }

                    TemplatedItemsList <ItemsView <Cell>, Cell> til = Element.TemplatedItems.GetGroup(g);

                    double headerHeight = GetHeight(templateReusables, Control.GroupHeaderTemplate, til);
                    y += headerHeight;

                    for (var i = 0; i < til.Count; i++)
                    {
                        Cell cell = til[i];

                        double contentHeight = GetHeight(templateReusables, Control.ItemTemplate, cell);

                        if ((ReferenceEquals(til.BindingContext, e.Group) || e.Group == null) && ReferenceEquals(cell.BindingContext, e.Item))
                        {
                            targetHeaderHeight = headerHeight;
                            targetHeight       = contentHeight;
                            found = true;
                            break;
                        }

                        y += contentHeight;
                    }
                }
            }
            else
            {
                for (var i = 0; i < Element.TemplatedItems.Count; i++)
                {
                    Cell cell = Element.TemplatedItems[i];

                    double height = GetHeight(templateReusables, Control.ItemTemplate, cell);

                    if (ReferenceEquals(cell.BindingContext, e.Item))
                    {
                        found        = true;
                        targetHeight = height;
                        break;
                    }

                    y += height;
                }
            }

            if (!found)
            {
                return;
            }

            ScrollToPosition position = e.Position;

            if (position == ScrollToPosition.MakeVisible)
            {
                if (y >= _viewport.Viewport.Top && y <= _viewport.Viewport.Bottom)
                {
                    return;
                }
                if (y > _viewport.Viewport.Bottom)
                {
                    position = ScrollToPosition.End;
                }
                else
                {
                    position = ScrollToPosition.Start;
                }
            }

            if (position == ScrollToPosition.Start && Element.IsGroupingEnabled)
            {
                y = y - targetHeaderHeight;
            }
            else if (position == ScrollToPosition.Center)
            {
                y = y - (_viewport.ActualHeight / 2 + targetHeight / 2);
            }
            else if (position == ScrollToPosition.End)
            {
                y = y - _viewport.ActualHeight + targetHeight;
            }

            double startY   = _viewport.Viewport.Y;
            double distance = y - startY;

            if (e.ShouldAnimate)
            {
                var animation = new Animation(v => { _viewport.SetViewportOrigin(new System.Windows.Point(0, startY + distance * v)); });

                animation.Commit(_animatable, "ScrollTo", length: 500, easing: Easing.CubicInOut);
            }
            else
            {
                _viewport.SetViewportOrigin(new System.Windows.Point(0, y));
            }
        }