在C#中验证TreeView的拖放操作的最佳方法
时间:2020-03-06 14:20:29 来源:igfitidea点击:
我想验证是否允许拖放操作。有效项可以来自我们的另一个"控件",也可以来自内部自定义树视图。目前我有这个:
bool CanDrop(DragEventArgs e) { bool allow = false; Point point = tree.PointToClient(new Point(e.X, e.Y)); TreeNode target = tree.GetNodeAt(point); if (target != null) { if (CanWrite(target)) //user permissions { if (e.Data.GetData(typeof(DataInfoObject)) != null) //from internal application { DataInfoObject info = (DataInfoObject)e.Data.GetData(typeof(DataInfoObject)); DragDataCollection data = info.GetData(typeof(DragDataCollection)) as DragDataCollection; if (data != null) { allow = true; } } else if (tree.SelectedNode.Tag.GetType() != typeof(TreeRow)) //node belongs to this & not a root node { if (TargetExistsInNode(tree.SelectedNode, target) == false) { if (e.Effect == DragDropEffects.Copy) { allow = true; } else if (e.Effect == DragDropEffects.Move) { allow = true; } } } } } return allow; }
我已经将所有检查代码移至此方法以尝试改进,但是对我来说,这仍然很糟糕!
如此多的逻辑,以及如此多的逻辑可以完成我希望树状视图完成的工作(例如," TargetExistsInNode"检查所拖动的节点是否被拖动至其子节点之一)。
验证控件输入的最佳方法是什么?
解决方案
我使用TreeNode.Tag属性存储构成逻辑的小型"控制器"对象。例如。:
class TreeNodeController { Entity data; virtual bool IsReadOnly { get; } virtual bool CanDrop(TreeNodeController source, DragDropEffects effect); virtual bool CanDrop(DataInfoObject info, DragDropEffects effect); virtual bool CanRename(); } class ParentNodeController : TreeNodeController { override bool IsReadOnly { get { return data.IsReadOnly; } } override bool CanDrop(TreeNodeController source, DragDropEffect effect) { return !IsReadOnly && !data.IsChildOf(source.data) && effect == DragDropEffect.Move; } virtual bool CanDrop(DataInfoObject info, DragDropEffects effect) { return info.DragDataCollection != null; } override bool CanRename() { return !data.IsReadOnly && data.HasName; } } class LeafNodeController : TreeNodeController { override bool CanDrop(TreeNodeController source, DragDropEffect effect) { return false; } }
然后我的CanDrop会是这样的:
bool CanDrop(DragDropEventArgs args) { Point point = tree.PointToClient(new Point(e.X, e.Y)); TreeNode target = tree.GetNodeAt(point); TreeNodeController targetController = target.Tag as TreeNodeController; DataInfoObject info = args.GetData(typeof(DataInfoObject)) as DataInfoObject; TreeNodeController sourceController = args.GetData(typeof(TreeNodeController)) as TreeNodeController; if (info != null) return targetController.CanDrop(info, e.Effect); if (sourceController != null) return targetController.CanDrop(sourceController, e.Effect); return false; }
现在,对于我添加到树中的每类对象,我可以通过选择要放置在Tag对象中的TreeNodeController来专门化行为。
没有严格回答问题,但是我发现代码中有一个错误。DragDropEffects
设置了flags属性,因此我们可以使e.Effect
为复制和移动的按位组合。在这种情况下,代码将错误地返回false。