private void UpdateDropCommandParameter(DragEventArgs eventArgs, int targetIndex)
        {
            if (_dropCommandParameter == null)
            {
                _dropCommandParameter = new DropCommandParameter();
            }

            _dropCommandParameter.DragEventArgs = eventArgs;
            _dropCommandParameter.TargetIndex   = targetIndex;
        }
        private void OnDragLeave(object sender, DragEventArgs eventArgs)
        {
            _dropCommandParameter = null;

            RemoveDropAdorner();

            // There may be multiple DragEnter/DragOver/DragLeave events within one frame.
            // Defer showing/hiding of preview to avoid flickering.
            Dispatcher.BeginInvoke(new Action(UpdateDragAdornerVisibility));
        }
        private void DisableDrop()
        {
            // Abort any drag-and-drop.
            RemoveDragAdorner();
            RemoveDropAdorner();
            _dropCommandParameter = null;

            // Unregister event handlers.
            AssociatedObject.DragEnter -= OnDragEnterOrDragOver;
            AssociatedObject.DragOver  -= OnDragEnterOrDragOver;
            AssociatedObject.DragLeave -= OnDragLeave;
            AssociatedObject.Drop      -= OnDrop;
        }
        private void ExecuteDrop(DropCommandParameter parameter)
        {
            // parameter.DragSource is the AssociatedObject that started the drag-and-drop.
            // We could store this object in a static field.
            //ItemsControl sourceItemsControl = parameter.DragSource as ItemsControl;
            var targetItemsControl = parameter.AssociatedObject as ItemsControl;

            if (targetItemsControl != null && _dragCommandParameter != null)
            {
                // Special case: Item dragged and dropped on the same ItemsControl.
                // In this case we first remove the item from the source ItemsControl.
                if ((parameter.DragEventArgs.Effects & DragDropEffects.Move) != 0)
                {
                    int indexRemoved = RemoveItemFromItemsControl(targetItemsControl, parameter.Data);
                    if (indexRemoved != -1 && indexRemoved < parameter.TargetIndex)
                    {
                        // The item was dragged to a later position within the same ItemsControl.
                        // --> Update the insertion index.
                        parameter.TargetIndex--;
                    }

                    // Set a flag to indicate that the DragCommand should not do anything.
                    // We have already taken care of the source.
                    _sourceUpdated = true;
                }
            }

            // Insert data into target.
            var targetContentControl = parameter.AssociatedObject as ContentControl;

            if (targetContentControl != null)
            {
                if (_dragCommandParameter != null)
                {
                    // We are dragging from and dropping into the same control. --> Do nothing.
                    parameter.DragEventArgs.Effects = DragDropEffects.None;
                }
                else
                {
                    // Target is ContentControl. --> Set data as content.
                    targetContentControl.Content = parameter.Data;
                }
            }
            else if (targetItemsControl != null)
            {
                // Target is ItemsControl. --> Add data to items.
                InsertItemInItemsControl(targetItemsControl, parameter.Data, parameter.TargetIndex);
            }
        }
        private bool CanExecuteDrop(DropCommandParameter parameter)
        {
            // Update effect.
            bool isMoveAllowed = (parameter.DragEventArgs.AllowedEffects & DragDropEffects.Move) != 0;
            bool isCopyAllowed = (parameter.DragEventArgs.AllowedEffects & DragDropEffects.Copy) != 0;

            if (!isMoveAllowed && !isCopyAllowed)
            {
                parameter.DragEventArgs.Effects = DragDropEffects.None;
            }
            else
            {
                if (isMoveAllowed && isCopyAllowed)
                {
                    bool isCtrlPressed = (parameter.DragEventArgs.KeyStates & DragDropKeyStates.ControlKey) != 0;
                    parameter.DragEventArgs.Effects = isCtrlPressed ? DragDropEffects.Copy : DragDropEffects.Move;
                }
            }

            // Extract data.
            object draggedData = GetData(parameter.DragEventArgs.Data);

            parameter.Data = draggedData;

            if (draggedData == null)
            {
                return(false);
            }

            var itemsControl = AssociatedObject as ItemsControl;

            if (itemsControl != null)
            {
                // The target is an ItemsControl.
                // --> Only permit drop if the ItemsSource is compatible with the data.
                if (!CanInsertDataInItemsControl(draggedData, itemsControl))
                {
                    return(false);
                }
            }

            return(true);
        }
        private void OnDrop(object sender, DragEventArgs eventArgs)
        {
            try
            {
                if (eventArgs.Handled)
                {
                    return;
                }

                eventArgs.Handled = true;

                // Check where the mouse is and if we should drop onto or between
                // items of an ItemsControl.
                FrameworkElement targetItemContainer;
                bool             isVertical;
                bool             insertAfter;
                int targetIndex;
                DetermineDropTarget(eventArgs, out targetItemContainer, out isVertical, out insertAfter, out targetIndex);

                UpdateDropCommandParameter(eventArgs, targetIndex);

                var dropCommand = DropCommand ?? DefaultDropCommand;
                if (dropCommand.CanExecute(_dropCommandParameter))
                {
                    dropCommand.Execute(_dropCommandParameter);

                    // DragEventArgs.Effects is reported back by DragDrop.DoDragDrop.
                    eventArgs.Effects = _dropCommandParameter.DragEventArgs.Effects;
                }
            }
            finally
            {
                RemoveDragAdorner();
                RemoveDropAdorner();
                _dropCommandParameter = null;
            }
        }