본문 바로가기
C#

🛠 WPF TreeView에서 ContextMenu로 노드 조작 기능 구현

by samie 2025. 4. 23.
WPF TreeView ContextMenu로 노드 조작 기능 구현

🛠 WPF TreeView에서 ContextMenu로 노드 조작 기능 구현

이번 포스트에서는 TreeView 항목에 우클릭 메뉴(ContextMenu)를 추가하고, 노드 추가 / 삭제 / 이름 변경 기능을 구현하는 방법을 알아봅니다.

📌 목차

  • 1. ContextMenu 구성
  • 2. Command 패턴 적용
  • 3. 노드 조작 메서드
  • 4. 확장 아이디어

1. ContextMenu 구성

XAML에서 TreeViewItemContextMenu를 정의합니다.

<TreeView ItemsSource="{Binding Categories}">
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
      <StackPanel Orientation="Horizontal">
        <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" />
        <TextBlock Text="{Binding Name}" Margin="5,0,0,0" />
        <StackPanel.ContextMenu>
          <ContextMenu>
            <MenuItem Header="노드 추가" Command="{Binding DataContext.AddNodeCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" />
            <MenuItem Header="노드 삭제" Command="{Binding DataContext.DeleteNodeCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" />
            <MenuItem Header="이름 변경" Command="{Binding DataContext.RenameNodeCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}" />
          </ContextMenu>
        </StackPanel.ContextMenu>
      </StackPanel>
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

2. ViewModel에서 Command 패턴 적용

RelayCommand를 사용해 각 기능을 ICommand로 바인딩합니다.

public ICommand AddNodeCommand { get; }
public ICommand DeleteNodeCommand { get; }
public ICommand RenameNodeCommand { get; }

public MainViewModel()
{
    AddNodeCommand = new RelayCommand<Category>(AddNode);
    DeleteNodeCommand = new RelayCommand<Category>(DeleteNode);
    RenameNodeCommand = new RelayCommand<Category>(RenameNode);
}

3. 노드 조작 메서드 구현

private void AddNode(Category? parent)
{
    if (parent == null) return;
    var newNode = new Category { Name = "새 노드", Parent = parent };
    parent.Children.Add(newNode);
}

private void DeleteNode(Category? node)
{
    if (node?.Parent == null) return;
    node.Parent.Children.Remove(node);
}

private void RenameNode(Category? node)
{
    if (node == null) return;
    node.Name = "이름 변경됨"; // 실제로는 팝업창이나 입력창으로 사용자 입력 받기
}

Tip: 실제 앱에서는 이름 변경을 위한 팝업 입력창을 구현하거나 TextBox → TextBlock 토글 방식도 유용합니다.

4. 확장 아이디어

  • 이름 변경을 TextBox 인라인 편집으로 개선
  • 드래그 앤 드롭으로 노드 이동 기능 추가
  • 삭제 시 자식 노드가 있는 경우 경고 표시

✅ 마무리

TreeView에 ContextMenu를 활용하면 UI 사용성이 한층 강화됩니다.
간단한 명령 처리만으로도 복잡한 트리 구조를 유연하게 다룰 수 있죠.

👉 다음 편에서는 TreeView 노드 드래그 앤 드롭(Drag & Drop)으로 구조 변경 기능을 구현해보겠습니다!