Лучший способ проверить операции перетаскивания для TreeView в C#

StackOverflow https://stackoverflow.com/questions/91127

Вопрос

Я хочу убедиться, что операция перетаскивания разрешена.Допустимый элемент может быть получен из другого нашего "элемента управления" или внутри пользовательского treeview.В настоящее время у меня есть это:

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

Я перенес весь проверочный код в этот метод, чтобы попытаться улучшить ситуацию, но для меня это все равно ужасно!

Так много логики, и так много ее для выполнения вещей, которые, как я ожидал, treeview сделает сам (например."TargetExistsInNode" проверяет, перетаскивается ли перетаскиваемый узел к одному из его дочерних элементов).

Каков наилучший способ проверки входных данных для элемента управления?

Это было полезно?

Решение

Я использую свойство TreeNode.Tag для хранения небольших объектов "controller", которые составляют логику.Например.:

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 поместить в объект тега.

Другие советы

Не совсем отвечаю на ваш вопрос, но я заметил ошибку в вашем коде.DragDropEffects установлен ли атрибут flags, чтобы вы могли получить e.Effect быть побитовой комбинацией копирования и перемещения.В этом случае ваш код неверно вернет значение false.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top