public static void AddHandler(this UIElement that, SW.ExtendedRoutedEvent routedEvent, Delegate handler, bool handledEventsToo)
        {
            if (routedEvent == null)
            {
                throw new ArgumentNullException("routedEvent");
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }

            SW.DragEventHandler dragEventHandler = handler as SW.DragEventHandler;
            if (targetEvents.Contains(routedEvent) && dragEventHandler == null)
            {
                throw new InvalidOperationException(System.Windows.Controls.Properties.Resources.UIElementExtendedRoutedEventExtensions_TypeOfHandlerMustBeDragEventHandler);
            }

            if (routedEvent == SW.DragDrop.DragEnterEvent)
            {
                SW.DragDrop.AddDragEnterHandler(that, dragEventHandler, handledEventsToo);
            }
            else if (routedEvent == SW.DragDrop.DragOverEvent)
            {
                SW.DragDrop.AddDragOverHandler(that, dragEventHandler, handledEventsToo);
            }
            else if (routedEvent == SW.DragDrop.DragLeaveEvent)
            {
                SW.DragDrop.AddDragLeaveHandler(that, dragEventHandler, handledEventsToo);
            }
            else if (routedEvent == SW.DragDrop.DropEvent)
            {
                SW.DragDrop.AddDropHandler(that, dragEventHandler, handledEventsToo);
            }
            else if (routedEvent == SW.DragDrop.GiveFeedbackEvent)
            {
                SW.GiveFeedbackEventHandler giveFeedbackHandler = handler as SW.GiveFeedbackEventHandler;
                if (giveFeedbackHandler == null)
                {
                    throw new InvalidOperationException(System.Windows.Controls.Properties.Resources.UIElementExtendedRoutedEventExtensions_TypeOfHandlerMustBeGiveFeedbackEventHandler);
                }
                SW.DragDrop.AddGiveFeedbackHandler(that, giveFeedbackHandler, handledEventsToo);
            }
            else if (routedEvent == SW.DragDrop.QueryContinueDragEvent)
            {
                SW.QueryContinueDragEventHandler queryContinueFeedbackHandler = handler as SW.QueryContinueDragEventHandler;
                if (queryContinueFeedbackHandler == null)
                {
                    throw new InvalidOperationException(System.Windows.Controls.Properties.Resources.UIElementExtendedRoutedEventExtensions_TypeOfHandlerMustBeQueryContinueDragEventHandler);
                }
                SW.DragDrop.AddQueryContinueDragHandler(that, queryContinueFeedbackHandler, handledEventsToo);
            }
        }
 /// <summary>
 /// Returns an observable that returns a SW.DragDropKeyStates value
 /// whenever it changes, even if one of the events involved
 /// is handled.
 /// </summary>
 /// <param name="that">The element to listen to.</param>
 /// <param name="initialState">The initial state SW.DragDropKeyStates.
 /// </param>
 /// <returns>An observable that returns a SW.DragDropKeyStates value
 /// whenever it changes, even if one of the events involved
 /// is handled.</returns>
 internal static IObservable<SW.DragDropKeyStates> GetKeyStateChangedAlways(
     this UIElement that,
     SW.DragDropKeyStates initialState)
 {
     return
         GetKeyStateChanged(that.GetMouseLeftButtonDownAlways(), that.GetMouseLeftButtonUpAlways(), that.GetKeyDownAlways(), that.GetKeyUpAlways(), initialState);
 }
        /// <summary>
        /// Returns an observable that returns a SW.DragDropKeyStates value
        /// whenever it changes, even if one of the events involved
        /// is handled or occurs in a sibling.
        /// </summary>
        /// <param name="that">The element to listen to.</param>
        /// <param name="initialState">The initial state SW.DragDropKeyStates.
        /// </param>
        /// <returns>An observable that returns a SW.DragDropKeyStates value
        /// whenever it changes, even if one of the events involved
        /// is handled.</returns>
        internal static IObservable<SW.DragDropKeyStates> GetKeyStateChangedOnSelfAndSiblingsAlways(this UIElement that, SW.DragDropKeyStates initialState)
        {
            IEnumerable<UIElement> popupRoots =
                VisualTreeExtensions.GetVisualDescendants(that)
                    .OfType<Popup>()
                    .Select(popup => popup.Child)
                    .Where(popupRoot => popupRoot != null);

            return GetKeyStateChanged(
                popupRoots
                    .Select(popupRoot => popupRoot.GetMouseLeftButtonDownAlways())
                    .Aggregate(that.GetMouseLeftButtonDownAlways(), (left, right) => left.Merge(right)),
                popupRoots
                    .Select(popupRoot => popupRoot.GetMouseLeftButtonUpAlways())
                    .Aggregate(that.GetMouseLeftButtonUpAlways(), (left, right) => left.Merge(right)),
                popupRoots
                    .Select(popupRoot => popupRoot.GetKeyUpAlways())
                    .Aggregate(that.GetKeyUpAlways(), (left, right) => left.Merge(right)),
                popupRoots
                    .Select(popupRoot => popupRoot.GetKeyDownAlways())
                    .Aggregate(that.GetKeyDownAlways(), (left, right) => left.Merge(right)),
                initialState);                    
        }
 /// <summary>
 /// Returns an observable that returns a SW.DragDropKeyStates value.  The
 /// observable is composed of mouse down and up observables and key down
 /// and up observables.
 /// </summary>
 /// <param name="mouseDownObservable">An event raised when a mouse 
 /// button is depressed.</param>
 /// <param name="mouseUpObservable">An event raised when a mouse button
 /// is released.</param>
 /// <param name="keyDownObservable">An event raised when a key is
 /// pressed down.</param> 
 /// <param name="keyUpObservable">An event raised when a key is 
 /// released.</param>
 /// <param name="initialState">The initial state of the drag and
 /// drop keys.</param>
 /// <returns>An observable that returns a SW.DragDropKeyStates value
 /// whenever it changes, even if one of the events involved
 /// is handled.</returns>
 private static IObservable<SW.DragDropKeyStates> GetKeyStateChanged(
     IObservable<Event<MouseButtonEventArgs>> mouseDownObservable, 
     IObservable<Event<MouseButtonEventArgs>> mouseUpObservable, 
     IObservable<Event<KeyEventArgs>> keyDownObservable, 
     IObservable<Event<KeyEventArgs>> keyUpObservable,
     SW.DragDropKeyStates initialState)
 {
     return
         mouseDownObservable
             .Select(ev => Tuple.Create(true, SW.DragDropKeyStates.LeftMouseButton))
             .Merge(
                 mouseUpObservable
                     .Select(ev => Tuple.Create(false, SW.DragDropKeyStates.LeftMouseButton)))
             .Merge(
                     keyUpObservable
                     .Select(ev => Tuple.Create(false, ToDragDropKeyStates(ev.EventArgs.Key))))
             .Merge(
                     keyDownObservable
                     .Select(ev => Tuple.Create(true, ToDragDropKeyStates(ev.EventArgs.Key))))
             .Scan<Tuple<bool, SW.DragDropKeyStates>, SW.DragDropKeyStates>(
                 initialState,
                 (acc, current) =>
                 {
                     if (current.Item1)
                     {
                         return acc | current.Item2;
                     }
                     else
                     {
                         return acc & ~current.Item2;
                     }
                 });
 }