/// <summary> /// Determines the values of the following properties: /// targetItemContainer, insertionIndex, and isInFirstHalf /// </summary> /// <remarks> /// If the types of the dragged data and ItemsControl's source are compatible, /// there are 3 situations to have into account when deciding the drop target: /// 1. mouse is over an items container /// 2. mouse is over the empty part of an ItemsControl, but ItemsControl is not empty /// 3. mouse is over an empty ItemsControl. /// The goal of this method is to decide on the values of the following properties: /// targetItemContainer, insertionIndex and isInFirstHalf. /// </remarks> private void DecideDropTarget(DragEventArgs e) { int targetItemsControlCount = this.targetItemsControl.Items.Count; object draggedItem = e.Data.GetData(this.format.Name); if (IsDropDataTypeAllowed(draggedItem)) { if (targetItemsControlCount > 0) { this.hasVerticalOrientation = DragDropUtilities.HasVerticalOrientation(this.targetItemsControl.ItemContainerGenerator.ContainerFromIndex(0) as FrameworkElement); this.targetItemContainer = targetItemsControl.ContainerFromElement((DependencyObject)e.OriginalSource) as FrameworkElement; if (this.targetItemContainer != null) { Point positionRelativeToItemContainer = e.GetPosition(this.targetItemContainer); this.isInFirstHalf = DragDropUtilities.IsInFirstHalf(this.targetItemContainer, positionRelativeToItemContainer, this.hasVerticalOrientation); this.insertionIndex = this.targetItemsControl.ItemContainerGenerator.IndexFromContainer(this.targetItemContainer); if (!this.isInFirstHalf) { this.insertionIndex++; } } else { this.targetItemContainer = this.targetItemsControl.ItemContainerGenerator.ContainerFromIndex(targetItemsControlCount - 1) as FrameworkElement; this.isInFirstHalf = false; this.insertionIndex = targetItemsControlCount; } } else { this.targetItemContainer = null; this.insertionIndex = 0; } } else { this.targetItemContainer = null; this.insertionIndex = -1; e.Effects = DragDropEffects.None; } }
/// <summary> /// Handles the PreviewDrop event of a DropTarget ItemsControl /// </summary> private void DropTarget_PreviewDrop(object sender, DragEventArgs e) { object draggedItem = e.Data.GetData(this.format.Name); int indexRemoved = -1; if (draggedItem != null) { if (this.sourceItemsControl != null) { if ((e.Effects & DragDropEffects.Move) != 0) { indexRemoved = DragDropUtilities.RemoveItemFromItemsControl(this.sourceItemsControl, draggedItem); } // This happens when we drag an item to a later position within the same ItemsControl. if (indexRemoved != -1 && this.sourceItemsControl == this.targetItemsControl && indexRemoved < this.insertionIndex) { this.insertionIndex--; } } DragDropUtilities.InsertItemInItemsControl(this.targetItemsControl, draggedItem, this.insertionIndex); RemoveDraggedAdorner(); if (GetIsInsertionAdornerEnabled(sender as Visual)) { RemoveInsertionAdorner(); } var element = sender as FrameworkElement; if (element != null) { var args = new OnDropEventArgs(OnDropEvent, e, draggedItem); element.RaiseEvent(args); } } e.Handled = true; }