示例#1
0
        /// <summary>
        ///     Called when the user releases a drag. Moves the item within the source list and then resets everything.
        /// </summary>
        private void dragInterceptor_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            if (dragItem == null)
            {
                return;
            }

            if (dropTargetIndex >= 0)
            {
                MoveItem(dragItem, dropTargetIndex);
            }

            if (dragItemContainer != null)
            {
                dragItemContainer.Visibility = Visibility.Visible;
                dragItemContainer.Opacity = 0;
                AnimateDrop(dragItemContainer);
                dragItemContainer = null;
            }

            dragScrollDelta = 0;
            dropTargetIndex = -1;
            ClearDropTarget();
        }
示例#2
0
        /// <summary>
        ///     Called when the user presses down on the transparent drag-interceptor. Identifies the targed
        ///     drag handle and list item and prepares for a drag operation.
        /// </summary>
        private void dragInterceptor_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            if (dragItem != null)
            {
                return;
            }

            if (itemsPanel == null)
            {
                var scrollItemsPresenter = (ItemsPresenter) scrollViewer.Content;
                itemsPanel = (Panel) VisualTreeHelper.GetChild(scrollItemsPresenter, 0);
            }

            GeneralTransform interceptorTransform = dragInterceptor.TransformToVisual(
                Application.Current.RootVisual);
            Point targetPoint = interceptorTransform.Transform(e.ManipulationOrigin);
            targetPoint = GetHostCoordinates(targetPoint);

            List<UIElement> targetElements = VisualTreeHelper.FindElementsInHostCoordinates(
                targetPoint, itemsPanel).ToList();
            ReorderListBoxItem targetItemContainer = targetElements.OfType<ReorderListBoxItem>().FirstOrDefault();
            if (targetItemContainer != null && targetElements.Contains(targetItemContainer.DragHandle))
            {
                VisualStateManager.GoToState(targetItemContainer, ReorderListBoxItem.DraggingState, true);

                GeneralTransform targetItemTransform = targetItemContainer.TransformToVisual(dragInterceptor);
                Point targetItemOrigin = targetItemTransform.Transform(new Point(0, 0));
                Canvas.SetLeft(dragIndicator, targetItemOrigin.X);
                Canvas.SetTop(dragIndicator, targetItemOrigin.Y);
                dragIndicator.Width = targetItemContainer.RenderSize.Width;
                dragIndicator.Height = targetItemContainer.RenderSize.Height;

                dragItemContainer = targetItemContainer;
                dragItem = dragItemContainer.Content;
                isDragItemSelected = dragItemContainer.IsSelected;

                dragInterceptorRect = interceptorTransform.TransformBounds(
                    new Rect(new Point(0, 0), dragInterceptor.RenderSize));

                dropTargetIndex = -1;
            }
        }
示例#3
0
        /// <summary>
        ///     Creates a storyboard to animate the visible moves of a rearrange.
        /// </summary>
        private Storyboard CreateRearrangeStoryboard(IEnumerable<RearrangeItemInfo> visibleMoves,
            Duration animationDuration)
        {
            var storyboard = new Storyboard();

            ReorderListBoxItem temporaryItemContainer = null;

            foreach (RearrangeItemInfo move in visibleMoves)
            {
                var itemSize = new Size(rearrangeCanvas.RenderSize.Width, move.Height);

                ReorderListBoxItem itemContainer = null;
                if (move.ToIndex >= 0)
                {
                    itemContainer = (ReorderListBoxItem) ItemContainerGenerator.ContainerFromIndex(move.ToIndex);
                }
                if (itemContainer == null)
                {
                    if (temporaryItemContainer == null)
                    {
                        temporaryItemContainer = new ReorderListBoxItem();
                    }

                    itemContainer = temporaryItemContainer;
                    itemContainer.Width = itemSize.Width;
                    itemContainer.Height = itemSize.Height;
                    rearrangeCanvas.Children.Add(itemContainer);
                    PrepareContainerForItemOverride(itemContainer, move.Item);
                    itemContainer.UpdateLayout();
                }

                var itemSnapshot = new WriteableBitmap((int) itemSize.Width, (int) itemSize.Height);
                itemSnapshot.Render(itemContainer, null);
                itemSnapshot.Invalidate();

                var itemImage = new Image();
                itemImage.Width = itemSize.Width;
                itemImage.Height = itemSize.Height;
                itemImage.Source = itemSnapshot;
                itemImage.RenderTransform = new TranslateTransform();
                rearrangeCanvas.Children.Add(itemImage);

                if (itemContainer == temporaryItemContainer)
                {
                    rearrangeCanvas.Children.Remove(itemContainer);
                }

                if (!Double.IsNaN(move.FromY) && !Double.IsNaN(move.ToY))
                {
                    Canvas.SetTop(itemImage, move.FromY);
                    if (move.FromY != move.ToY)
                    {
                        var moveAnimation = new DoubleAnimation();
                        moveAnimation.Duration = animationDuration;
                        Storyboard.SetTarget(moveAnimation, itemImage.RenderTransform);
                        Storyboard.SetTargetProperty(moveAnimation, new PropertyPath(TranslateTransform.YProperty));
                        moveAnimation.To = move.ToY - move.FromY;
                        storyboard.Children.Add(moveAnimation);
                    }
                }
                else if (Double.IsNaN(move.FromY) != Double.IsNaN(move.ToY))
                {
                    if (move.FromIndex >= 0 && move.ToIndex >= 0)
                    {
                        var moveAnimation = new DoubleAnimation();
                        moveAnimation.Duration = animationDuration;
                        Storyboard.SetTarget(moveAnimation, itemImage.RenderTransform);
                        Storyboard.SetTargetProperty(moveAnimation, new PropertyPath(TranslateTransform.YProperty));

                        const double animationDistance = 200;
                        if (!Double.IsNaN(move.FromY))
                        {
                            Canvas.SetTop(itemImage, move.FromY);
                            if (move.FromIndex < move.ToIndex)
                            {
                                moveAnimation.To = animationDistance;
                            }
                            else if (move.FromIndex > move.ToIndex)
                            {
                                moveAnimation.To = -animationDistance;
                            }
                        }
                        else
                        {
                            Canvas.SetTop(itemImage, move.ToY);
                            if (move.FromIndex < move.ToIndex)
                            {
                                moveAnimation.From = -animationDistance;
                            }
                            else if (move.FromIndex > move.ToIndex)
                            {
                                moveAnimation.From = animationDistance;
                            }
                        }

                        storyboard.Children.Add(moveAnimation);
                    }

                    var fadeAnimation = new DoubleAnimation();
                    fadeAnimation.Duration = animationDuration;
                    Storyboard.SetTarget(fadeAnimation, itemImage);
                    Storyboard.SetTargetProperty(fadeAnimation, new PropertyPath(OpacityProperty));

                    if (Double.IsNaN(move.FromY))
                    {
                        itemImage.Opacity = 0.0;
                        fadeAnimation.To = 1.0;
                        Canvas.SetTop(itemImage, move.ToY);
                    }
                    else
                    {
                        itemImage.Opacity = 1.0;
                        fadeAnimation.To = 0.0;
                        Canvas.SetTop(itemImage, move.FromY);
                    }

                    storyboard.Children.Add(fadeAnimation);
                }
            }

            return storyboard;
        }
示例#4
0
        /// <summary>
        ///     Slides the drag indicator (item snapshot) to the location of the dropped item,
        ///     then performs the visibility swap and removes the dragging visual state.
        /// </summary>
        private void AnimateDrop(ReorderListBoxItem itemContainer)
        {
            GeneralTransform itemTransform = itemContainer.TransformToVisual(dragInterceptor);
            Rect itemRect = itemTransform.TransformBounds(new Rect(new Point(0, 0), itemContainer.RenderSize));
            double delta = Math.Abs(itemRect.Y - Canvas.GetTop(dragIndicator) -
                                    ((TranslateTransform) dragIndicator.RenderTransform).Y);
            if (delta > 0)
            {
                // Adjust the duration based on the distance, so the speed will be constant.

                //Anton Sizikov: an OverflowExceptionOverflow when itemRect.Height equals to zero.
                TimeSpan duration;
                if (itemRect.Height == 0.0d)
                {
                    duration = TimeSpan.FromSeconds(0);
                }
                else
                {
                    double seconds = 0.25*delta/itemRect.Height;
                    duration = TimeSpan.FromSeconds(seconds);
                }

                var dropStoryboard = new Storyboard();
                var moveToDropAnimation = new DoubleAnimation();
                Storyboard.SetTarget(moveToDropAnimation, dragIndicator.RenderTransform);
                Storyboard.SetTargetProperty(moveToDropAnimation, new PropertyPath(TranslateTransform.YProperty));
                moveToDropAnimation.To = itemRect.Y - Canvas.GetTop(dragIndicator);
                moveToDropAnimation.Duration = duration;
                dropStoryboard.Children.Add(moveToDropAnimation);

                dropStoryboard.Completed += delegate
                {
                    dragItem = null;
                    itemContainer.Opacity = 1;
                    dragIndicator.Visibility = Visibility.Collapsed;
                    dragIndicator.Source = null;
                    ((TranslateTransform) dragIndicator.RenderTransform).Y = 0;
                    VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.NotDraggingState, true);
                };
                dropStoryboard.Begin();
            }
            else
            {
                // There was no need for an animation, so do the visibility swap right now.
                dragItem = null;
                itemContainer.Opacity = 1;
                dragIndicator.Visibility = Visibility.Collapsed;
                dragIndicator.Source = null;
                VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.NotDraggingState, true);
            }
        }
示例#5
0
        /// <summary>
        ///     Ensures that a possibly-recycled item container (ReorderListBoxItem) is ready to display a list item.
        /// </summary>
        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);

            var itemContainer = (ReorderListBoxItem) element;
            itemContainer.ApplyTemplate(); // Loads visual states.

            // Set this state before binding to avoid showing the visual transition in this case.
            string reorderState = IsReorderEnabled
                ? ReorderListBoxItem.ReorderEnabledState
                : ReorderListBoxItem.ReorderDisabledState;
            VisualStateManager.GoToState(itemContainer, reorderState, false);

            itemContainer.SetBinding(ReorderListBoxItem.IsReorderEnabledProperty,
                new Binding(IsReorderEnabledPropertyName) {Source = this});

            if (item == dragItem)
            {
                itemContainer.IsSelected = isDragItemSelected;
                VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.DraggingState, false);

                if (dropTargetIndex >= 0)
                {
                    // The item's dragIndicator is currently being moved, so the item itself is hidden.
                    itemContainer.Visibility = Visibility.Collapsed;
                    dragItemContainer = itemContainer;
                }
                else
                {
                    itemContainer.Opacity = 0;
                    Dispatcher.BeginInvoke(() => AnimateDrop(itemContainer));
                }
            }
            else
            {
                VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.NotDraggingState, false);
            }
        }
示例#6
0
        /// <summary>
        ///     Called when an item container (ReorderListBoxItem) is being removed from the list panel.
        ///     This may be because the item was removed from the list or because the item is now outside
        ///     the virtualization region (because ListBox uses a VirtualizingStackPanel as its items panel).
        /// </summary>
        protected override void ClearContainerForItemOverride(DependencyObject element, object item)
        {
            base.ClearContainerForItemOverride(element, item);

            var itemContainer = (ReorderListBoxItem) element;
            if (itemContainer == dragItemContainer)
            {
                dragItemContainer.Visibility = Visibility.Visible;
                dragItemContainer = null;
            }
        }
示例#7
0
        /// <summary>
        ///     Updates the targeted index -- that is the index where the item will be moved to if dropped at this point.
        /// </summary>
        private void UpdateDropTargetIndex(ReorderListBoxItem targetItemContainer, bool after)
        {
            int dragItemIndex = Items.IndexOf(dragItem);
            int targetItemIndex = Items.IndexOf(targetItemContainer.Content);

            int newDropTargetIndex;
            if (targetItemIndex == dragItemIndex)
            {
                newDropTargetIndex = dragItemIndex;
            }
            else
            {
                newDropTargetIndex = targetItemIndex + (after ? 1 : 0) - (targetItemIndex >= dragItemIndex ? 1 : 0);
            }

            if (newDropTargetIndex != dropTargetIndex)
            {
                dropTargetIndex = newDropTargetIndex;
            }
        }