Лучший способ проверить операции перетаскивания для TreeView в C#
-
01-07-2019 - |
Вопрос
Я хочу убедиться, что операция перетаскивания разрешена.Допустимый элемент может быть получен из другого нашего "элемента управления" или внутри пользовательского 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.