/// <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); }
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(); }