简体   繁体   English

在C#中验证TreeView的拖放操作的最佳方法

[英]Best way to validate drag/drop operations for a TreeView in C#

I want to verify a drag & drop operation is allowed. 我想验证是否允许拖放操作。 A valid item can come from another one of our "controls", or internally from within the custom treeview. 有效项可以来自我们的另一个“控件”,也可以来自内部自定义树视图。 Currently I have this: 目前我有这个:

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;
}

I've moved all the checking code to this method to try to improve things, but to me this is still horrible! 我已经将所有检查代码移至此方法以尝试改进,但是对我来说,这仍然很糟糕!

So much logic, and so much of it to do things that I'd expect the treeview would do itself (eg. "TargetExistsInNode" checks whether the dragged node is being dragged to one of its children). 如此多的逻辑,以及如此多的逻辑可以做我希望树状视图完成的事情(例如,“ TargetExistsInNode”检查被拖动的节点是否被拖动到其子节点之一)。

What is the best way to validate input to a control? 验证控件输入的最佳方法是什么?

I use the TreeNode.Tag property to store small "controller" objects that makes up the logic. 我使用TreeNode.Tag属性存储构成逻辑的小型“控制器”对象。 Eg: 例如:

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;
  }
}

Then my CanDrop would be something like: 然后我的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;
}

Now for each class of objects that I add to the tree I can specialize the behaviour by choosing which TreeNodeController to put in the Tag object. 现在,对于我添加到树中的每类对象,我可以通过选择要放置在Tag对象中的TreeNodeController来专门化行为。

Not strictly answering your question, but I've spotted a bug in your code. 没有严格回答您的问题,但是我发现您的代码中存在错误。 DragDropEffects has the flags attribute set so you could get e.Effect to be a bitwise combination of copy and move. DragDropEffects设置了flags属性,因此您可以将e.Effect作为复制和移动的按位组合。 In which case your code would incorrectly return false. 在这种情况下,您的代码将错误地返回false。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM