// IControlOverrides protected override void OnDrop(Windows.UI.Xaml.DragEventArgs e) { var args = e; if (args.AcceptedOperation == DataPackageOperation.Move && !args.Handled) { if (m_draggedTreeViewNode != null && IsIndexValid(m_emptySlotIndex)) { // Get the node at which we will insert TreeViewNode insertAtNode = NodeAtFlatIndex(m_emptySlotIndex); if (IsMutiSelectWithSelectedItems) { // Multiselect drag and drop. In the selected items, find all the selected subtrees // and move each of those subtrees. var selectedRootNodes = GetRootsOfSelectedSubtrees(); // Loop through in reverse order because we are inserting above the previous item to get the order correct. for (int i = selectedRootNodes.Count - 1; i >= 0; --i) { MoveNodeInto(selectedRootNodes[i], insertAtNode); } } else { MoveNodeInto(m_draggedTreeViewNode, insertAtNode); } UpdateDropTargetDropEffect(false, false, null); args.Handled = true; } } base.OnDrop(e); }
protected override void OnDragEnter(Windows.UI.Xaml.DragEventArgs args) { if (!args.Handled) { UpdateDropTargetDropEffect(false, false, null); } base.OnDragEnter(args); }
protected override void OnDragLeave(Windows.UI.Xaml.DragEventArgs args) { m_emptySlotIndex = -1; base.OnDragLeave(args); if (!args.Handled) { UpdateDropTargetDropEffect(false, true, null); } }
protected override void OnDragOver(Windows.UI.Xaml.DragEventArgs args) { if (!args.Handled) { args.AcceptedOperation = DataPackageOperation.None; IInsertionPanel insertionPanel = (IInsertionPanel)ItemsPanelRoot; // reorder is only supported with panels that implement IInsertionPanel if (insertionPanel != null && m_draggedTreeViewNode != null && CanReorderItems) { int aboveIndex = -1; int belowIndex = -1; var itemsSource = ListViewModel; int size = itemsSource.Count; var point = args.GetPosition((UIElement)insertionPanel); insertionPanel.GetInsertionIndexes(point, out aboveIndex, out belowIndex); // a value of -1 means we're inserting at the end of the list or before the last item if (belowIndex == -1) { // this allows the next part of this code to test if we're dropping before or after the last item belowIndex = size - 1; } // if we have an insertion point // a value of 0 means we're inserting at the beginning // a value greater than size - 1 means we're inserting at the end as items are collapsing if (belowIndex > size - 1) { // don't go out of bounds // since items might be collapsing as we're dragging m_emptySlotIndex = size - 1; } else if (belowIndex > 0 && m_draggedTreeViewNode != null) { m_emptySlotIndex = -1; TreeViewNode tvi = m_draggedTreeViewNode; if (ListViewModel.IndexOfNode(tvi, out var draggedIndex)) { int indexToUse = (draggedIndex < belowIndex) ? belowIndex : (belowIndex - 1); var item = ContainerFromIndex(indexToUse); if (item != null) { var treeViewItem = (TreeViewItem)item; var pointInsideItem = args.GetPosition(treeViewItem); // if the point is in the top half of the item // we need to insert before that item if (pointInsideItem.Y < treeViewItem.ActualHeight / 2) { m_emptySlotIndex = belowIndex - 1; } else { m_emptySlotIndex = belowIndex; } } } } else { // top of the list m_emptySlotIndex = 0; } bool allowReorder = true; if (IsFlatIndexValid(m_emptySlotIndex)) { var insertAtNode = NodeAtFlatIndex(m_emptySlotIndex); if (IsMultiselect) { // If insertAtNode is in the selected items, then we do not want to allow a dropping. var selectedItems = ListViewModel.SelectedNodes; for (var i = 0; i < selectedItems.Count; i++) { var selectedNode = selectedItems[i]; if (selectedNode == insertAtNode) { allowReorder = false; break; } } } else { if (m_draggedTreeViewNode != null && insertAtNode != null && insertAtNode.Parent != null) { var insertContainer = ContainerFromNode(insertAtNode.Parent); if (insertContainer != null) { allowReorder = ((TreeViewItem)insertContainer).AllowDrop; } } } } else { // m_emptySlotIndex does not exist in the ViewModel - don't allow the reorder. allowReorder = false; } if (allowReorder) { args.AcceptedOperation = DataPackageOperation.Move; } else { m_emptySlotIndex = -1; args.AcceptedOperation = DataPackageOperation.None; args.Handled = true; } } UpdateDropTargetDropEffect(false, false, null); } base.OnDragOver(args); }
// Required as OnDrop is protected and can't be accessed from outside internal void OnDropInternal(Windows.UI.Xaml.DragEventArgs e) => OnDrop(e);