public static TreeDragInformation FromNodes(TreeNodeAdv[] sourceNodes, TreeNodeAdv targetNode, NodePosition position) { var dragInfo = new TreeDragInformation(); dragInfo.SourceTable = (sourceNodes.First().Tag as ITabularTableObject)?.Table; dragInfo.TargetTable = (targetNode.Tag as ITabularTableObject)?.Table ?? (position == NodePosition.Inside ? targetNode.Tag as Table : null); dragInfo.SourceHierarchy = (sourceNodes.First().Tag as Level)?.Hierarchy; dragInfo.TargetHierarchy = (targetNode.Tag as Level)?.Hierarchy ?? (position == NodePosition.Inside ? targetNode.Tag as Hierarchy : null); //dragInfo.TargetFolder = position == NodePosition.Inside ? targetNode.Tag as IDetailObjectContainer : (targetNode.Tag as IDetailObject)?.GetContainer(); dragInfo.TargetLevel = targetNode.Tag as Level; if (dragInfo.TargetLevel != null) { dragInfo.TargetOrdinal = dragInfo.TargetLevel.Ordinal; if (position == NodePosition.After) { dragInfo.TargetOrdinal++; } } else if (dragInfo.TargetHierarchy != null) { dragInfo.TargetOrdinal = dragInfo.TargetHierarchy.Levels.Count; } return(dragInfo); }
/// <summary> /// Contains logic for determining if a drag/drop operation is legal. Additionally, specify doDrop = true to actually perform the drop (if it is legal). /// </summary> /// <param name="sourceNodes"></param> /// <param name="targetNode"></param> /// <param name="position"></param> /// <param name="doDrop"></param> /// <returns></returns> public virtual bool CanDrop(TreeNodeAdv[] sourceNodes, TreeNodeAdv targetNode, NodePosition position) { if ((FilterActive && FilterMode == FilterMode.Flat) || sourceNodes == null || sourceNodes.Length == 0) { return(false); } DragInfo = TreeDragInformation.FromNodes(sourceNodes, targetNode, position); // Must not drop nodes on themselves or any of their children: if (sourceNodes.Contains(targetNode)) { return(false); } if (sourceNodes.Any(n => targetNode.HasAncestor(n))) { return(false); } // Drag operations that require the source and destination table to be the same: if (DragInfo.SameTable) { // Dragging foldered objects into or out of folders: if (sourceNodes.All(n => n.Tag is IFolderObject)) { if (targetNode.Tag is IFolder) { return(SetDropMode(DropMode.Folder)); } } // Dragging into a hierarchy: if (DragInfo.TargetHierarchy != null) { // Dragging levels within a hierarchy or between hierarchies: if (sourceNodes.All(n => n.Tag is Level)) { return(SetDropMode(DragInfo.SameHierarchy ? DropMode.ReorderLevels : DropMode.LevelMove)); } // Dragging columns into a hierarchy: if (sourceNodes.All(n => n.Tag is Column)) { // Prevent drop if the hierarchy already contains the dragged column(s) as a level: if (DragInfo.TargetHierarchy.Levels.Any(l => sourceNodes.Select(n => n.Tag as Column).Contains(l.Column))) { return(false); } return(SetDropMode(DropMode.AddColumns)); } } } else { // Dragging measures and calculated columns between tables is also allowed: if (sourceNodes.All(n => n.Tag is CalculatedColumn || n.Tag is Measure)) { if (targetNode.Tag is Table && position == NodePosition.Inside) { return(SetDropMode(DropMode.MoveObject)); } } } // All other cases not allowed: return(false); }