/// <summary> /// Raises the attached QueryContinueDrag 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 OnQueryContinueDrag(this DependencyObject element, SW.QueryContinueDragEventArgs args) { if (!args.Handled) { IAcceptDrop acceptDrop = element as IAcceptDrop; if (acceptDrop != null) { acceptDrop.OnQueryContinueDrag(args); } } ExtendedRoutedEventHandlerCollection <SW.QueryContinueDragEventHandler, SW.QueryContinueDragEventArgs> handlers = element.GetQueryContinueDragHandlers(); if (handlers != null) { handlers.Raise(args); } }
/// <summary> /// Raises the QueryContinueDragEvent on the drag source. /// </summary> /// <returns>Information about the QueryContinueDrag event.</returns> private SW.QueryContinueDragEventArgs OnDragSourceQueryContinueDrag() { SW.QueryContinueDragEventArgs queryContinueDragEventArgs = new SW.QueryContinueDragEventArgs() { Action = SW.DragAction.Continue, EscapePressed = _escapePressed, KeyStates = KeyStates, OriginalSource = _dragSource }; DependencyObject dragSource = _dragSource; if (dragSource != null) { queryContinueDragEventArgs = dragSource.RaiseRoutedEvent( queryContinueDragEventArgs, (acc, e) => acc.OnQueryContinueDrag(e)); } if (!queryContinueDragEventArgs.Handled) { if (queryContinueDragEventArgs.EscapePressed) { queryContinueDragEventArgs.Action = SW.DragAction.Cancel; queryContinueDragEventArgs.Handled = true; } else if ((queryContinueDragEventArgs.KeyStates & SW.DragDropKeyStates.LeftMouseButton) != SW.DragDropKeyStates.LeftMouseButton) { queryContinueDragEventArgs.Action = (_lastGiveFeedbackEventArgs == null || _lastGiveFeedbackEventArgs.Effects != SW.DragDropEffects.None) ? SW.DragAction.Drop : SW.DragAction.Cancel; queryContinueDragEventArgs.Handled = true; } } _dragSourceQueryContinueDrag.OnNext( Event.Create( _dragSource, queryContinueDragEventArgs)); return(queryContinueDragEventArgs); }
public IDisposable Subscribe(IObserver <SW.DragDropEffects> observer) { if (IsDragging) { throw new InvalidOperationException("A drag operation is already in progress."); } IsDragging = true; // Always execute a QueryContinueDrag first. _dragStarting.Take(1) .ObserveOnDispatcher() .Subscribe( dragEventArgs => { SW.QueryContinueDragEventArgs args = OnDragSourceQueryContinueDrag(); if (!(args.Handled && args.Action == SW.DragAction.Cancel)) { OnDragSourceGiveFeedback(_lastDragEventArgs); _dragStarted.OnNext(dragEventArgs); } }); IObservable <SW.DragDropKeyStates> keyStatesChanged = from dragStarted in _dragStarting where Application.Current != null from keyState in Application.Current.RootVisual .GetKeyStateChangedOnSelfAndSiblingsAlways(KeyStates) .TakeUntil(_dragCompleted) select keyState; keyStatesChanged.Subscribe(keyState => KeyStates = keyState); IObservable <bool> escapePressedChanged = from dragStated in _dragStarting where Application.Current != null from escapePressed in Application.Current.RootVisual .GetEscapePressedChangedOnSelfAndSiblingsAlways() .TakeUntil(_dragCompleted) select escapePressed; escapePressedChanged.Subscribe(pressed => _escapePressed = pressed); Observable .Merge( keyStatesChanged.IgnoreAll(), escapePressedChanged.IgnoreAll()) .TakeUntil(_dragCompleted) .ObserveOnDispatcher() .Subscribe(_ => RaiseDragSourceEvents(_lastDragEventArgs)); IObservable <IEvent <SW.DragEventArgs> > dragOver = from dragStartedEvent in _dragStarted let mouseMoveDragOver = GetMouseMoveDragOver() from dragMouseOverEvent in mouseMoveDragOver.TakeUntil(_dragCompleted) from pulseDragMouseOverEvent in Observable.Merge( Observable.Return(dragMouseOverEvent), Observable .Interval(TimeSpan.FromMilliseconds(MouseOverPulseIntervalInMilliseconds)) .ObserveOnDispatcher() .Select(_ => { UIElement originalSource = dragMouseOverEvent.EventArgs.OriginalSource as UIElement; if (originalSource != null) { Point pointWithinOriginalSource = dragMouseOverEvent.EventArgs.GetPosition((UIElement)dragMouseOverEvent.EventArgs.OriginalSource); // if point is no longer within original source find the element // in the tree that contains the point and make it the original source (and sender) // or the next dragover event. if (!new Rect(new Point(0, 0), originalSource.GetSize()).Contains(pointWithinOriginalSource)) { originalSource = GetDragOverOriginalSource(dragMouseOverEvent.EventArgs); } } return(Event.Create(originalSource, new SW.DragEventArgs(dragMouseOverEvent.EventArgs) { OriginalSource = originalSource })); }) .TakeUntil( Observable.Merge( mouseMoveDragOver.IgnoreAll(), _dragCompleted.IgnoreAll()))) where IsDragging select pulseDragMouseOverEvent; dragOver .ObserveOnDispatcher() .Subscribe(dragOverEvent => OnDragOver(dragOverEvent.Sender, dragOverEvent.EventArgs)); _dragStarting.OnNext(Event.Create(_dragSource, _dragStartEventArgs)); _dragCompleted .ObserveOnDispatcher() .Subscribe(observer); return(new AnonymousDisposable(() => { Debug.Assert(false, "Should never detach from DragOperation."); })); }