🧲 WPF TreeView 드래그 앤 드롭 기능 구현
TreeView를 사용하다 보면 노드를 끌어서 순서를 바꾸거나 다른 부모 노드 아래로 이동시키고 싶은 경우가 많습니다.
이번 포스트에서는 WPF TreeView에서 드래그 앤 드롭(Drag & Drop) 기능을 구현하는 방법을 설명합니다.
목차
1. Category 모델 구성
public class Category
{
public string Name { get; set; }
public ObservableCollection<Category> Children { get; set; } = new();
public Category? Parent { get; set; }
}
Parent 프로퍼티를 활용해 트리 구조에서 상위 노드를 추적할 수 있게 합니다.
2. TreeView 이벤트 처리 (Drag & Drop)
private Point _startPoint;
private void TreeView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(null);
}
private void TreeView_MouseMove(object sender, MouseEventArgs e)
{
Point mousePos = e.GetPosition(null);
Vector diff = _startPoint - mousePos;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
TreeView treeView = sender as TreeView;
TreeViewItem? item = FindAncestor<TreeViewItem>((DependencyObject)e.OriginalSource);
if (item != null && item.DataContext is Category category)
{
DragDrop.DoDragDrop(item, category, DragDropEffects.Move);
}
}
}
private void TreeView_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(Category)))
{
Category draggedItem = (Category)e.Data.GetData(typeof(Category))!;
TreeViewItem? targetItem = FindAncestor<TreeViewItem>((DependencyObject)e.OriginalSource);
if (targetItem != null && targetItem.DataContext is Category targetCategory)
{
MoveCategory(draggedItem, targetCategory);
}
}
}
마우스를 움직이는 거리로 Drag 시작을 감지하고, Drop 시 대상 아이템에 맞춰 트리를 업데이트합니다.
3. 아이템 이동 로직 구현
private void MoveCategory(Category source, Category destination)
{
if (source == destination || IsChildOf(source, destination))
return;
source.Parent?.Children.Remove(source);
source.Parent = destination;
destination.Children.Add(source);
}
private bool IsChildOf(Category parent, Category child)
{
if (child.Parent == null) return false;
if (child.Parent == parent) return true;
return IsChildOf(parent, child.Parent);
}
이동 시 순환 참조를 방지하고, 기존 부모에서 제거한 후 새 부모에 추가하는 방식입니다.
4. 사용자 피드백 효과 (Highlight 등)
드롭 가능한 위치에만 효과를 주고 싶다면 XAML에 이벤트와 스타일을 추가해보세요.
<TreeView
PreviewMouseLeftButtonDown="TreeView_PreviewMouseLeftButtonDown"
MouseMove="TreeView_MouseMove"
AllowDrop="True"
Drop="TreeView_Drop">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
5. 마무리 및 다음 편 예고
- WPF TreeView에서도 드래그 앤 드롭이 가능하며
- 노드 구조를 동적으로 업데이트할 수 있습니다
- MVVM 구조와도 함께 사용할 수 있도록 구조 설계가 중요합니다
다음 편에서는 TreeView와 ContextMenu(오른쪽 클릭 메뉴)를 연동해서 노드를 삭제하거나 이름을 변경하는 기능을 구현해보겠습니다! ✂️
'C#' 카테고리의 다른 글
WPF TreeView 검색 기능 구현 (0) | 2025.04.16 |
---|---|
WPF TreeView ContextMenu로 노드 삭제 및 이름 변경 (0) | 2025.04.15 |
WPF TreeView 선택 상태 저장 및 복원 (0) | 2025.04.13 |
WPF TreeView 검색 기능 구현 (0) | 2025.04.12 |
WPF TreeView 체크박스 노드 구현 (0) | 2025.04.11 |