private void MultiSelectTreeviewElementsGroupsDragVerifyHandler(object sender, DragVerifyEventArgs e)
{
// we need to go through all nodes that would be moved (source nodes), and check if there's any
// problem moving any of them to the target node (circular references, etc.), since it's possible
// for a element to exist multiple times in the treeview as different treenodes.
List<ElementNode> nodes = new List<ElementNode>(e.SourceNodes.Select(x => x.Tag as ElementNode));
// now get a list of invalid children for this target node, and check all the remaining nodes against it.
// If any of them fail, the entire operation should fail, as it would be an invalid move.
// the target node will be the actual target node if it is directly on it, otherwise it would be the parent
// of the target node if it would be dragged above/below the taget element (as it would be put alongside it).
// also keep track of the 'permitted' nodes: this is used when dragging alongside another element: any children
// of the new parent node are considered OK, as we might just be shuffling them around. Normally, this would
// be A Bad Thing, since it would seem like we're adding a child to the group it's already in. (This is only
// the case when moving; if copying, it should be disabled. That's checked later.)
IEnumerable<ElementNode> invalidNodesForTarget = null;
IEnumerable<ElementNode> permittedNodesForTarget = null;
if (e.DragBetweenNodes == DragBetweenNodes.DragOnTargetNode || e.DragBetweenNodes == DragBetweenNodes.DragBelowTargetNode && e.TargetNode.IsExpanded) {
invalidNodesForTarget = (e.TargetNode.Tag as ElementNode).InvalidChildren();
permittedNodesForTarget = new HashSet<ElementNode>();
} else {
if (e.TargetNode.Parent == null) {
invalidNodesForTarget = VixenSystem.Nodes.InvalidRootNodes;
permittedNodesForTarget = VixenSystem.Nodes.GetRootNodes();
} else {
invalidNodesForTarget = (e.TargetNode.Parent.Tag as ElementNode).InvalidChildren();
permittedNodesForTarget = (e.TargetNode.Parent.Tag as ElementNode).Children;
}
}
if ((e.KeyState & 8) != 0) { // the CTRL key
e.DragMode = DragDropEffects.Copy;
permittedNodesForTarget = new HashSet<ElementNode>();
} else {
e.DragMode = DragDropEffects.Move;
}
IEnumerable<ElementNode> invalidSourceNodes = invalidNodesForTarget.Intersect(nodes);
if (invalidSourceNodes.Count() > 0) {
if (invalidSourceNodes.Intersect(permittedNodesForTarget).Count() == invalidSourceNodes.Count())
e.ValidDragTarget = true;
else
e.ValidDragTarget = false;
} else {
e.ValidDragTarget = true;
}
}