/// <summary> /// This scrolls the items control when we hit a boundary /// </summary> /// <param name="itemsControl"></param> /// <param name="e"></param> private void HandleDragScrolling(ItemsControl itemsControl, DragEventArgs e) { bool?isMouseAtTop = DragUtilities.IsMousePointerAtTop(itemsControl, e.GetPosition(itemsControl)); if (isMouseAtTop.HasValue) { if (this._dragScrollWaitCounter == DragWaitCounterThreshold) { this._dragScrollWaitCounter = 0; ScrollViewer scrollViewer = DragUtilities.FindScrollViewer(itemsControl); if (scrollViewer != null && scrollViewer.CanContentScroll && scrollViewer.ComputedVerticalScrollBarVisibility == Visibility.Visible) { scrollViewer.ScrollToVerticalOffset((isMouseAtTop.Value) ? scrollViewer.VerticalOffset - 1.0 : scrollViewer.VerticalOffset + 1.0); e.Effects = DragDropEffects.Scroll; } } else { this._dragScrollWaitCounter++; } } else { e.Effects = GetDropEffectType(e.AllowedEffects, e.KeyStates); } }
/// <summary> /// Update the position of the insertion point marker /// </summary> /// <param name="itemsControl"></param> /// <param name="e"></param> private void UpdateInsertAdorner(ItemsControl itemsControl, DragEventArgs e) { if (this._insertAdorner != null) { this._insertAdorner.InTopHalf = DragUtilities.IsPointInTopHalf(itemsControl, e); this._insertAdorner.InvalidateVisual(); } }
/// <summary> /// Determine the proper insertion index /// </summary> /// <param name="itemsControl"></param> /// <param name="e"></param> /// <returns></returns> private static int FindInsertionIndex(ItemsControl itemsControl, DragEventArgs e) { UIElement dropTargetContainer = DragUtilities.GetItemContainerFromPoint(itemsControl, e.GetPosition(itemsControl)); if (dropTargetContainer != null) { int index = itemsControl.ItemContainerGenerator.IndexFromContainer(dropTargetContainer); return(DragUtilities.IsPointInTopHalf(itemsControl, e) ? index : index + 1); } return(itemsControl.Items.Count); }
/// <summary> /// Drop started /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void PreviewDrop(object sender, DragEventArgs e) { var itemsControl = (ItemsControl)sender; this.DestroyAdorners(); e.Handled = true; if (e.Data.GetDataPresent(this.ItemTypeKey)) { int index = FindInsertionIndex(itemsControl, e); DragInfo data = e.Data.GetData(this.ItemTypeKey) as DragInfo; if (data != null && (!data.AllowOnlySelf || itemsControl == data.Source)) { var allowedEffects = e.AllowedEffects; if (this.DropInitiated != null) { DragDropEventArgs de = new DragDropEventArgs(data.Source, itemsControl, data.Data, index) { AllowedEffects = allowedEffects }; this.DropInitiated(this, de); allowedEffects = de.AllowedEffects; if (de.Cancel) { e.Effects = DragDropEffects.None; return; } } object itemToAdd = data.Data; e.Effects = GetDropEffectType(allowedEffects, e.KeyStates); if (DragUtilities.DoesItemExists(itemsControl, itemToAdd) && (e.Effects == DragDropEffects.Move || (e.Effects & DragDropEffects.Move) > 0 && (e.KeyStates & DragDropKeyStates.ControlKey) > 0)) { DragUtilities.RemoveItem(itemsControl, itemToAdd); // Recalc our position based on the removal index = FindInsertionIndex(itemsControl, e); } DragUtilities.AddItem(itemsControl, itemToAdd, index); DragUtilities.SelectItem(itemsControl, index); } else { e.Effects = DragDropEffects.None; } } else { e.Effects = DragDropEffects.None; } }
/// <summary> /// Starts the drag/drop operation. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var itemsControl = (ItemsControl)sender; Point p = e.GetPosition(itemsControl); this._data = DragUtilities.GetDataObjectFromItemsControl(itemsControl, p); if (this._data != null) { this._isMouseDown = true; this._dragStartPosition = p; } }
/// <summary> /// Initialize the insertion point marker /// </summary> /// <param name="itemsControl"></param> /// <param name="e"></param> private void InitializeInsertAdorner(ItemsControl itemsControl, DragEventArgs e) { if (this._insertAdorner == null && this.ShowInsertAdorner) { UIElement itemContainer = DragUtilities.GetItemContainerFromPoint(itemsControl, e.GetPosition(itemsControl)); if (itemContainer != null) { this._insertAdorner = new InsertAdorner(DragUtilities.IsPointInTopHalf(itemsControl, e), DragUtilities.IsItemControlOrientationHorizontal(itemsControl), itemContainer, AdornerLayer.GetAdornerLayer(itemsControl), itemsControl); } } }
/// <summary> /// New drop target identified /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void PreviewDragEnter(object sender, DragEventArgs e) { e.Handled = true; e.Effects = DragDropEffects.None; var itemsControl = (ItemsControl)sender; // Do not allow if sorted. if (!DragUtilities.CanReorderCollectionView(itemsControl)) { return; } if (e.Data.GetDataPresent(this.ItemTypeKey)) { DragInfo data = e.Data.GetData(this.ItemTypeKey) as DragInfo; if (data != null) { if (!data.AllowOnlySelf || itemsControl == data.Source) { var allowedEffects = e.AllowedEffects; if (itemsControl == data.Source && !this.AllowSelf) { allowedEffects = DragDropEffects.None; } else if (this.DropEnter != null) { DragDropEventArgs de = new DragDropEventArgs(data.Source, itemsControl, data.Data) { AllowedEffects = allowedEffects }; this.DropEnter(this, de); allowedEffects = de.AllowedEffects; if (de.Cancel) { return; } } this.InitializeDragAdorner(itemsControl, data.Data, e.GetPosition(itemsControl)); e.Effects = GetDropEffectType(allowedEffects, e.KeyStates); if (e.Effects != DragDropEffects.None) { this.InitializeInsertAdorner(itemsControl, e); } } } } }
/// <summary> /// This starts the drag operation from the given ItemsControl /// </summary> /// <param name="itemsControl"></param> private void DragStarted(ItemsControl itemsControl) { DragDropEffects allowedEffects = DragDropEffects.Copy | DragDropEffects.Move; if (this.DragInitiated != null) { var dde = new DragDropEventArgs(itemsControl, null, this._data) { AllowedEffects = allowedEffects }; this.DragInitiated(this, dde); if (dde.Cancel) { this.ResetState(); return; } allowedEffects = dde.AllowedEffects; } UIElement draggedItemContainer = DragUtilities.GetItemContainerFromPoint(itemsControl, this._dragStartPosition); this._isDragging = true; DataObject dObject = new DataObject(this.ItemTypeKey, new DragInfo { Data = this._data, Source = itemsControl, AllowOnlySelf = this.AllowOnlySelf }); DragDropEffects e = DragDrop.DoDragDrop(itemsControl, dObject, allowedEffects); if ((e & DragDropEffects.Move) != 0) { if (draggedItemContainer != null) { int dragItemIndex = itemsControl.ItemContainerGenerator.IndexFromContainer(draggedItemContainer); DragUtilities.RemoveItem(itemsControl, dragItemIndex); } else { DragUtilities.RemoveItem(itemsControl, this._data); } } this.ResetState(); }
/// <summary> /// Display the drag indicator /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void PreviewMouseMove(object sender, MouseEventArgs e) { if (this._isMouseDown) { var itemsControl = (ItemsControl)sender; Point currentPosition = e.GetPosition(itemsControl); if ((this._isDragging == false) && (Math.Abs(currentPosition.X - this._dragStartPosition.X) > SystemParameters.MinimumHorizontalDragDistance) || (Math.Abs(currentPosition.Y - this._dragStartPosition.Y) > SystemParameters.MinimumVerticalDragDistance)) { // Do not allow if sorted and we only allow this element as // the drop target. if (!DragUtilities.CanReorderCollectionView(itemsControl) && this.AllowOnlySelf) { return; } this.DragStarted(itemsControl); } } }