/// <summary> /// Initializes a new instance of the DropInfo class. /// </summary> /// /// <param name="sender"> /// The sender of the drag event. /// </param> /// /// <param name="e"> /// The drag event. /// </param> /// /// <param name="dragInfo"> /// Information about the source of the drag, if the drag came from within the framework. /// </param> public DropInfo(object sender, DragEventArgs e, DragInfo dragInfo) { var dataFormat = DragDrop.DataFormat.Name; this.Data = (e.Data.GetDataPresent(dataFormat)) ? e.Data.GetData(dataFormat) : e.Data; this.DragInfo = dragInfo; this.KeyStates = e.KeyStates; this.VisualTarget = sender as UIElement; // if drop target isn't a ItemsControl if (!(this.VisualTarget is ItemsControl)) { // try to find next ItemsControl var itemsControl = VisualTreeExtensions.GetVisualAncestor <ItemsControl>(this.VisualTarget); if (itemsControl != null) { // now check if this ItemsControl is a drop target if (DragDrop.GetIsDropTarget(itemsControl)) { this.VisualTarget = itemsControl; } } } // visual target can be null, so give us a point... this.DropPosition = this.VisualTarget != null?e.GetPosition(this.VisualTarget) : new Point(); if (this.VisualTarget is ItemsControl) { var itemsControl = (ItemsControl)this.VisualTarget; var item = itemsControl.GetItemContainerAt(this.DropPosition); var directlyOverItem = item != null; this.TargetGroup = this.FindGroup(itemsControl, this.DropPosition); this.VisualTargetOrientation = itemsControl.GetItemsPanelOrientation(); this.VisualTargetFlowDirection = itemsControl.GetItemsPanelFlowDirection(); if (item == null) { item = itemsControl.GetItemContainerAt(this.DropPosition, this.VisualTargetOrientation); directlyOverItem = false; } if (item != null) { var itemParent = ItemsControl.ItemsControlFromItemContainer(item); this.InsertIndex = itemParent.ItemContainerGenerator.IndexFromContainer(item); this.TargetCollection = itemParent.ItemsSource ?? itemParent.Items; if (directlyOverItem || typeof(TreeViewItem).IsAssignableFrom(item.GetType())) { this.TargetItem = itemParent.ItemContainerGenerator.ItemFromContainer(item); this.VisualTargetItem = item; } var itemRenderSize = item.RenderSize; if (this.VisualTargetOrientation == Orientation.Vertical) { var currentYPos = e.GetPosition(item).Y; var targetHeight = itemRenderSize.Height; if (currentYPos > targetHeight / 2) { this.InsertIndex++; this.InsertPosition = RelativeInsertPosition.AfterTargetItem; } else { this.InsertPosition = RelativeInsertPosition.BeforeTargetItem; } if (currentYPos > targetHeight * 0.25 && currentYPos < targetHeight * 0.75) { this.InsertPosition |= RelativeInsertPosition.TargetItemCenter; } } else { var currentXPos = e.GetPosition(item).X; var targetWidth = itemRenderSize.Width; if ((this.VisualTargetFlowDirection == FlowDirection.RightToLeft && currentXPos < targetWidth / 2) || (this.VisualTargetFlowDirection == FlowDirection.LeftToRight && currentXPos > targetWidth / 2)) { this.InsertIndex++; this.InsertPosition = RelativeInsertPosition.AfterTargetItem; } else { this.InsertPosition = RelativeInsertPosition.BeforeTargetItem; } if (currentXPos > targetWidth * 0.25 && currentXPos < targetWidth * 0.75) { this.InsertPosition |= RelativeInsertPosition.TargetItemCenter; } #if DEBUG Console.WriteLine("==> DropInfo: {0}, {1}, {2}, X={3}", this.InsertPosition, item, this.InsertIndex, currentXPos); #endif } } else { this.TargetCollection = itemsControl.ItemsSource ?? itemsControl.Items; this.InsertIndex = itemsControl.Items.Count; } } }