/// <summary>
        /// Raises the attached DragEnter event on a element.
        /// </summary>
        /// <param name="element">The element to raise the event on.</param>
        /// <param name="args">Information about the event.</param>
        internal static void OnDragEnter(this DependencyObject element, SW.DragEventArgs args)
        {
            if (!args.Handled)
            {
                IAcceptDrop acceptDrop = element as IAcceptDrop;
                if (acceptDrop != null)
                {
                    acceptDrop.OnDragEnter(args);
                }
            }
            ExtendedRoutedEventHandlerCollection <SW.DragEventHandler, SW.DragEventArgs> handlers = element.GetDragEnterHandlers();

            if (handlers != null)
            {
                handlers.Raise(args);
            }
        }
        /// <summary>
        /// Raises the DragLeave event.
        /// </summary>
        private void OnDragLeave()
        {
            if (_currentDragOverElement != null)
            {
                SW.DragEventArgs eventArgs = new SW.DragEventArgs(_lastDragEventArgs)
                {
                    OriginalSource = _currentDragOverElement
                };

                DependencyObject acceptDrop = (DependencyObject)_currentDragOverElement;
                eventArgs =
                    RaiseRoutedDragEvent(
                        acceptDrop,
                        eventArgs,
                        (ancestor, args) => ancestor.OnDragLeave(args));
            }
        }
        /// <summary>
        /// This method raises the Drop event.
        /// </summary>
        private void OnTargetDrop()
        {
            UIElement dropTarget = _lastDragEventArgs.OriginalSource as UIElement;

            if (dropTarget != null && dropTarget.AllowDrop)
            {
                SW.DragEventArgs dropEventArgs =
                    RaiseRoutedDragEvent(dropTarget, _lastDragEventArgs, (acc, ev) => acc.OnDrop(ev));

                // Regardless of whether event args is handled and what the allowed effects are
                // WPF drag and drop always returns the effects after a drop event.
                _dragCompleted.OnNext(dropEventArgs.Effects);
            }
            else
            {
                _dragCompleted.OnNext(SW.DragDropEffects.None);
            }
        }
        /// <summary>
        /// Raises the DragOver event.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="eventArgs">Information about the event.</param>
        private void OnDragOver(object sender, SW.DragEventArgs eventArgs)
        {
            UIElement target = eventArgs.OriginalSource as UIElement;

            if (_currentDragOverElement != target)
            {
                OnDragEnter(sender, new SW.DragEventArgs(eventArgs));
            }

            DependencyObject acceptDrop = (DependencyObject)sender;

            eventArgs =
                RaiseRoutedDragEvent(
                    acceptDrop,
                    eventArgs,
                    (ancestor, args) => ancestor.OnDragOver(args));

            RaiseDragSourceEvents(eventArgs);
        }
        /// <summary>
        /// Initializes a new instance of the DragOperation class.
        /// </summary>
        /// <param name="dragSource">The source of the drag operation.</param>
        /// <param name="data">The data associated with the drag operation.
        /// </param>
        /// <param name="allowedEffects">The allowed effects of the drag
        /// operation.
        /// </param>
        /// <param name="initialKeyState">The initial state of the keys relevant
        /// to drag operations.</param>
        public DragOperation(DependencyObject dragSource, object data, SW.DragDropEffects allowedEffects, SW.DragDropKeyStates initialKeyState)
        {
            SW.IDataObject dataObject = data as SW.IDataObject;
            if (dataObject == null)
            {
                dataObject = new DataObject(data);
            }

            _allowedEffects = allowedEffects;
            KeyStates       = initialKeyState;

            _dragSource = dragSource;
            SW.DragEventArgs dragStartEventArgs =
                new SW.DragEventArgs()
            {
                OriginalSource = dragSource,
                AllowedEffects = allowedEffects,
                Effects        = allowedEffects,
                Data           = dataObject
            };

            _lastDragEventArgs = dragStartEventArgs;
            dragStartEventArgs.AllowedEffects = allowedEffects;
            dragStartEventArgs.Data           = dataObject;

            this._dragStartEventArgs = dragStartEventArgs;

            IObservable <Event <SW.QueryContinueDragEventArgs> > sourceQueryContinue =
                from dragStartedEvent in _dragStarting
                from queryContinueDragEvent in _dragSourceQueryContinueDrag.Until(_dragCompleted)
                where queryContinueDragEvent.EventArgs.Handled
                select queryContinueDragEvent;

            sourceQueryContinue
            .Where(queryContinueDragEvent => queryContinueDragEvent.EventArgs.Action == SW.DragAction.Drop)
            .Subscribe(queryContinueDragEvent => OnTargetDrop());

            sourceQueryContinue
            .Where(queryContinueDragEvent => queryContinueDragEvent.EventArgs.Action == SW.DragAction.Cancel)
            .Subscribe(queryContinueDragEvent => OnCancel());

            _dragCompleted.Subscribe(_ => IsDragging = false);
        }
        /// <summary>
        /// Raises the GiveFeedback event on the drag source.
        /// </summary>
        /// <param name="args">Information about the GiveFeedback event.
        /// </param>
        private void OnDragSourceGiveFeedback(SW.DragEventArgs args)
        {
            SW.DragDropEffects effects = _allowedEffects;

            if (args.Handled)
            {
                effects = _allowedEffects & args.Effects;
            }
            else
            {
                effects = GetDragDropEffects(_allowedEffects);
            }

            _lastGiveFeedbackEventArgs =
                new SW.GiveFeedbackEventArgs()
            {
                Effects        = effects,
                OriginalSource = _dragSource,
            };

            _dragSource.RaiseRoutedEvent(
                _lastGiveFeedbackEventArgs,
                (accept, e) => accept.OnGiveFeedback(e));
        }
        /// <summary>
        /// Retrieves the original source of a new DragOver event.  Attempts to
        /// determine the original source by finding the the deepest element
        /// in the tree that the mouse is over.
        /// </summary>
        /// <param name="args">Information about the drag event.</param>
        /// <returns>The original source of a new DragOver event.</returns>
        private static UIElement GetDragOverOriginalSource(SW.DragEventArgs args)
        {
            UIElement originalSource = args.OriginalSource as UIElement;
            // Use the previous original source and go to its root.
            // Note: this won't work if a popup appears on top of the
            // original source but it will work if the previous original source
            // is inside of a popup.
            UIElement rootVisual = originalSource.GetVisualAncestors().OfType <UIElement>().LastOrDefault();

            if (rootVisual != null)
            {
                // If the original source disappears (ex. a popup disappears),
                // use the root visual.
                rootVisual = Application.Current.RootVisual;

                originalSource =
                    FunctionalProgramming.TraverseBreadthFirst(
                        rootVisual,
                        node => node.GetVisualChildren().OfType <UIElement>(),
                        node => new Rect(new Point(0, 0), node.GetSize()).Contains(args.GetPosition(node)))
                    .LastOrDefault();
            }
            return(originalSource);
        }
Beispiel #8
0
        private void MovePopupAndRaiseEvents(double horizontalChange, double verticalChange)
        {
#if !(BRIDGE && MIGRATION)
            if (_popup != null)
            {
                //popup moving with the pointer
                _popup.HorizontalOffset += horizontalChange;
                _popup.VerticalOffset   += verticalChange;
            }

            // Prepare the "DragEventArgs" to pass to the raised events:
            Selection           selection           = new Selection(_sourceItemContainer);
            SelectionCollection selectionCollection = SelectionCollection.ToSelectionCollection(selection);
            DataObject          dataObject          = new DataObject();
            dataObject.SetData("ItemDragEventArgs", new ItemDragEventArgs(selectionCollection));
            MS.DragEventArgs dragOverEventArgs = new MS.DragEventArgs(dataObject);

            // Get the DragDropTarget element that is under the pointer, if any:
            TItemContainerType targetItemContainer;
            DragDropTarget <TItemsControlType, TItemContainerType> dragDropTargetUnderPointer = GetDragDropTargetUnderPointer(_pointerX, _pointerY, out targetItemContainer);

            // Check if the element under the pointer has changed since the last PointerMoved:
            if (_previousdragDropTargetUnderPointer != dragDropTargetUnderPointer)
            {
                //---------------------------------
                // IF WHAT IS UNDER THE POINTER HAS CHANGED
                //---------------------------------

                // Raise the DragLeave event of the element that was under the pointer before:
                if (_previousdragDropTargetUnderPointer != null && _previousdragDropTargetUnderPointer.DragLeave != null)
                {
                    _previousdragDropTargetUnderPointer.DragLeave(_previousdragDropTargetUnderPointer, new MS.DragEventArgs(dataObject));

                    // Reset the value of "_isDragCancelled" when leaving a control. This variable lets the user prevent a Drop on an element when the user sets e.Handled=true in the "DragOver" event of that element.
                    _isDragCancelled = false;
                }
                // Remember the element that is under the pointer:
                _previousdragDropTargetUnderPointer = dragDropTargetUnderPointer;

                // Raise the DragEnter event of the new element that is under the pointer:
                if (dragDropTargetUnderPointer != null && dragDropTargetUnderPointer.DragEnter != null)
                {
                    dragDropTargetUnderPointer.DragEnter(dragDropTargetUnderPointer, new MS.DragEventArgs(dataObject));
                }
            }

            if (dragDropTargetUnderPointer != null)
            {
                //---------------------------------
                // IF UNDER THE POINTER THERE IS A DRAGDROPPANEL
                //---------------------------------

                // Raise the DragOver:
                dragDropTargetUnderPointer.OnDragOver(dragOverEventArgs);

                // Cancel the drag drop operation if the user has marked the DragOver event as "handled":
                if (dragOverEventArgs.Handled && dragOverEventArgs.Effects == DragDropEffects.None)
                {
                    _isDragCancelled = true;
                }
            }

            // Show the appropriate icon depending on whether it is possible to drop or not:
            if (dragDropTargetUnderPointer != null && dragDropTargetUnderPointer.AllowDrop && !_isDragCancelled)
            {
                //---------------------------------
                // SHOW ICON "DRAG ALLOWED"
                //---------------------------------
                _iconArrow.Visibility = Visibility.Visible;
                _iconStop.Visibility  = Visibility.Collapsed;
            }
            else
            {
                //---------------------------------
                // SHOW ICON "DRAG FORBIDDEN"
                //---------------------------------
                _iconArrow.Visibility = Visibility.Collapsed;
                _iconStop.Visibility  = Visibility.Visible;
            }
#endif
        }
        /// <summary>
        /// Gets the insertion index within a drop target given information
        /// about a drag event.
        /// </summary>
        /// <param name="dropTarget">The drop target.</param>
        /// <param name="args">Information about a drag event.</param>
        /// <returns>The insertion index within the drop target.</returns>
        protected override int GetDropTargetInsertionIndexOverride(ItemsControl dropTarget, SW.DragEventArgs args)
        {
            ItemsControl itemsControl = GetItemsControlAncestor((DependencyObject)args.OriginalSource);

            // If the parent items control is the drop target then we're
            // appending the item into the child collection of the currently
            // hovered tree view item.
            if (itemsControl != dropTarget)
            {
                return(dropTarget.GetItemCount());
            }

            return(base.GetDropTargetInsertionIndexOverride(dropTarget, args));
        }
        /// <summary>
        /// Returns a geometry for the insertion indicator.
        /// </summary>
        /// <param name="dropTarget">The drop target.</param>
        /// <param name="insertionIndex">The insertion index within the drop
        /// target.</param>
        /// <param name="dragEventArgs">Information about the drag event.
        /// </param>
        /// <returns>The geometry for the insertion indicator.</returns>
        protected override Geometry GetInsertionIndicatorGeometry(ItemsControl dropTarget, int insertionIndex, SW.DragEventArgs dragEventArgs)
        {
            ItemsControl itemsControlAncestor = GetItemsControlAncestor((DependencyObject)dragEventArgs.OriginalSource);
            TreeViewItem treeViewItem         = dropTarget as TreeViewItem;

            // If the parent items control is the drop target then we're
            // appending the item into the child collection of the currently
            // hovered tree view item.
            if (treeViewItem != null && itemsControlAncestor != dropTarget)
            {
                GeneralTransform generalTransform = dropTarget.SafeTransformToVisual(this);
                if (generalTransform != null)
                {
                    Rect  dropTargetRect = GetTreeViewItemRectExcludingChildren(treeViewItem);
                    Point origin;
                    if (generalTransform.TryTransform(new Point(0, 0), out origin))
                    {
                        Point dropTargetPositionRelativeToDragDropTarget = origin;
                        dropTargetPositionRelativeToDragDropTarget.X += dropTargetRect.Left;
                        dropTargetPositionRelativeToDragDropTarget.Y += dropTargetRect.Top;
                        return(new RectangleGeometry {
                            Rect = new Rect(dropTargetPositionRelativeToDragDropTarget, new Size(dropTargetRect.Width, dropTargetRect.Height))
                        });
                    }
                }
            }

            return(base.GetInsertionIndicatorGeometry(dropTarget, insertionIndex, dragEventArgs));
        }
 /// <summary>
 /// This method is called whenever a target event is raised.
 /// </summary>
 /// <param name="args">Information about the drag target event.</param>
 protected override void OnDragEvent(Microsoft.Windows.DragEventArgs args)
 {
     SetEffects(args);
     base.OnDragEvent(args);
 }
        /// <summary>
        /// Prevents Move, Copy, or Link actions if an item is dragged into its
        /// descendent.
        /// </summary>
        /// <param name="args">Information about the drag event.</param>
        protected override void OnDragLeave(SW.DragEventArgs args)
        {
            base.OnDragLeave(args);

            _dragLeave.OnNext(Event.Create(this, args));
        }
        /// <summary>
        /// Prevents Move, Copy, or Link actions if an item is dragged into its
        /// descendent.
        /// </summary>
        /// <param name="args">Information about the drag event.</param>
        protected override void OnDragLeave(SW.DragEventArgs args)
        {
            base.OnDragLeave(args);

            _dragLeave.OnNext(new Event <SW.DragEventArgs>(this, args));
        }
        /// <summary>
        /// Raises the GiveFeedback and QueryContinueDrag events on the drag
        /// source.
        /// </summary>
        /// <param name="args">Information about the last drag event.</param>
        private void RaiseDragSourceEvents(SW.DragEventArgs args)
        {
            OnDragSourceGiveFeedback(args);

            OnDragSourceQueryContinueDrag();
        }