C#에서 TreeView에 대한 끌어서 놓기 작업의 유효성을 검사하는 가장 좋은 방법

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

문제

드래그 앤 드롭 작업이 허용되는지 확인하고 싶습니다.유효한 항목은 다른 "컨트롤"에서 나오거나 사용자 정의 트리 보기 내에서 내부적으로 나올 수 있습니다.현재 나는 이것을 가지고 있습니다 :

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 당신이 얻을 수 있도록 플래그 속성이 설정되어 있습니다 e.Effect 복사와 이동의 비트 조합이 됩니다.이 경우 코드가 false를 잘못 반환합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top