C# Tips


TreeNodeのDrag&Dropを実装する


TreeNodeのDrag&Dropを実装するには、結構実装することがあります。
具体的には、次のような手順を踏みます。
この例では、ツリーノードをドラッグ&ドラッグで移動できるようにします。
1. TreeViewのAllowDropプロパティをTrueに設定します。
2. ItemDragにドラッグを開始するコードを記述します。
3. DragEnterにドラッグがコントロール内に入った時の動作を記述します。
4. DragOverにドラッグ先のアイテムを展開するコードを記述します。
5. DragDropにドロップ後のコードを記述します。

private void treeViewMain_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
{
	TreeNode targetNode = null;
	TreeNode sourceNode = null;
				
	if(e.Data.GetDataPresent(typeof(TreeNode)))
	{
		Point point = treeViewMain.PointToClient(new Point(e.X, e.Y));
		targetNode = treeViewMain.GetNodeAt(point.X, point.Y);
		sourceNode = e.Data.GetData(typeof(TreeNode)) as TreeNode;
		int delta = treeViewMain.Height - point.Y; 
		if ((delta < treeViewMain.Height/2) && (delta > 0)) 
		{ 
			TreeNode tn = treeViewMain.GetNodeAt(point.X, point.Y); 
			if (tn.NextVisibleNode != null) 
				tn.NextVisibleNode.EnsureVisible();
		}
		if ((delta > treeViewMain.Height/2) && (delta < treeViewMain.Height))
		{
			TreeNode tn = treeViewMain.GetNodeAt(point.X, point.Y);
			if (tn.PrevVisibleNode != null)
				tn.PrevVisibleNode.EnsureVisible();
		}
	}

	if(targetNode != null)
	{
		targetNode.Expand();
		if(isTreeNodeMovable(sourceNode, targetNode))
		{
			e.Effect = DragDropEffects.Move;
		}
		else
		{
			e.Effect = DragDropEffects.None;
		}
	}
	else
	{
		e.Effect = DragDropEffects.None;
	}
}

private void treeViewMain_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
	if(e.Data.GetDataPresent(typeof(TreeNode)))
	{
		TreeNode sourceNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
		Point point = treeViewMain.PointToClient(new Point(e.X, e.Y));
		TreeNode targetNode = treeViewMain.GetNodeAt(point.X, point.Y);

		if(isTreeNodeMovable(sourceNode, targetNode))
		{
			TreeNode dragNode = sourceNode;
			treeViewMain.Nodes.Remove(sourceNode);
			targetNode.Nodes.Insert(targetNode.Index+1, dragNode);
		}
	}
}

private bool isTreeNodeMovable(TreeNode source, TreeNode target)
{
	if(target == null || source == null) return false;
	if(target == source) return false;
	if(target.Parent == source) return false;

	// Target cannot be a source's child
	if(isAncestor(target, source)) return false;
	return true;
}

private bool isAncestor(TreeNode descendant, TreeNode ancestor)
{
	TreeNode investigatedNode = descendant;
	while(investigatedNode != null)
	{
		if(investigatedNode == ancestor) return true;
		investigatedNode = investigatedNode.Parent; 
	}
	return false;
}

private void treeViewMain_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
{
	treeViewMain.DoDragDrop((TreeNode)e.Item, DragDropEffects.All);
}

private void treeViewMain_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
	if(e.Data.GetDataPresent(typeof(TreeNode)) && sender.Equals(treeViewMain))
	{
		e.Effect = DragDropEffects.Move;
	}
	else
	{
		e.Effect = DragDropEffects.None;
	}
}


目次に戻る
Copyright(c) 2008 WoodenSoldier Software