C# で TreeView のドラッグ アンド ドロップ操作を検証する最良の方法
-
01-07-2019 - |
質問
ドラッグ アンド ドロップ操作が許可されていることを確認したいと思います。有効な項目は、別の「コントロール」から取得することも、カスタム ツリービュー内から内部的に取得することもできます。現在、私はこれを持っています:
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
flags 属性が設定されているため、 e.Effect
コピーと移動をビットごとに組み合わせたものになります。この場合、コードは誤って false を返します。
所属していません StackOverflow