【问题标题】:Best way to validate drag/drop operations for a TreeView in C#在 C# 中验证 TreeView 的拖放操作的最佳方法
【发布时间】:2008-09-18 09:15:10
【问题描述】:

我想验证是否允许拖放操作。有效项目可以来自我们的另一个“控件”,也可以来自内部自定义树视图。目前我有这个:

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”检查被拖动的节点是否被拖动到它的一个子节点)。

验证控件输入的最佳方法是什么?

【问题讨论】:

    标签: c# validation user-controls treeview


    【解决方案1】:

    我使用 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;
    }
    

    现在,对于添加到树中的每一类对象,我可以通过选择将哪个 TreeNodeController 放入 Tag 对象来专门化行为。

    【讨论】:

      【解决方案2】:

      没有严格回答您的问题,但我在您的代码中发现了一个错误。 DragDropEffects 设置了 flags 属性,因此您可以让 e.Effect 成为复制和移动的按位组合。在这种情况下,您的代码将错误地返回 false。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多