본문 바로가기
C#

WPF TreeView와 MVVM Command 바인딩

by samie 2025. 4. 9.
WPF TreeView와 MVVM Command 바인딩

🧭 WPF TreeView에서 Command 바인딩 및 MVVM 패턴 적용

MVVM 패턴은 WPF 개발의 핵심입니다. 이번 글에서는 TreeView 컨트롤에서 항목을 클릭할 때 MVVM 방식으로 Command를 바인딩하고 처리하는 방법을 단계별로 알아봅니다.

1. MVVM 패턴에서 TreeView 처리 흐름

일반적으로 TreeView는 UI 요소에서 이벤트를 직접 처리합니다. 하지만 MVVM에서는 Command와 Binding으로 연결해야 합니다.

2. RelayCommand 클래스 정의

MVVM에서 ICommand 구현은 필수입니다. 가장 많이 쓰는 RelayCommand 예제는 다음과 같습니다.


public class RelayCommand : ICommand
{
    private readonly Action<object?> _execute;
    private readonly Predicate<object?>? _canExecute;

    public RelayCommand(Action<object?> execute, Predicate<object?>? canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    public event EventHandler? CanExecuteChanged;

    public bool CanExecute(object? parameter) => _canExecute?.Invoke(parameter) ?? true;

    public void Execute(object? parameter) => _execute(parameter);
}

3. ViewModel 구성하기

✔️ 데이터 모델


public class Category
{
    public string Name { get; set; }
    public ObservableCollection<Category> SubCategories { get; set; }
}

✔️ ViewModel 구성


public class MainViewModel
{
    public ObservableCollection<Category> Categories { get; set; }

    public ICommand CategorySelectedCommand { get; }

    public MainViewModel()
    {
        Categories = new ObservableCollection<Category>
        {
            new Category
            {
                Name = "프론트엔드",
                SubCategories = new ObservableCollection<Category>
                {
                    new Category { Name = "HTML" },
                    new Category { Name = "CSS" },
                }
            }
        };

        CategorySelectedCommand = new RelayCommand(OnCategorySelected);
    }

    private void OnCategorySelected(object? parameter)
    {
        if (parameter is Category selected)
        {
            MessageBox.Show($"선택된 항목: {selected.Name}");
        }
    }
}

4. TreeView XAML 및 이벤트 바인딩

WPF에서는 직접 TreeViewItem.Selected 이벤트를 사용할 수 없으므로, Interactivity 라이브러리 또는 Behaviors SDK를 활용하여 이벤트 → Command로 연결합니다.

📦 NuGet 패키지 설치

📄 XAML


<Window
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
  xmlns:local="clr-namespace:YourNamespace"
  ...>

  <TreeView ItemsSource="{Binding Categories}" Margin="10">
    <TreeView.ItemTemplate>
      <HierarchicalDataTemplate ItemsSource="{Binding SubCategories}">
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Name}" />
          <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseLeftButtonUp">
              <ei:CallMethodAction MethodName="Execute"
                TargetObject="{Binding DataContext.CategorySelectedCommand, RelativeSource={RelativeSource AncestorType=Window}}"
                />
            </i:EventTrigger>
          </i:Interaction.Triggers>
        </StackPanel>
      </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
  </TreeView>

</Window>

이 방식은 ViewModel 내 Command로 항목 클릭을 연결하는 표준 방식입니다.

5. 선택된 항목 추적까지 구현

추가로 선택된 항목을 추적하고 바인딩하려면 TreeView의 SelectedItem을 바인딩해야 합니다.

그러나 TreeView.SelectedItem은 바인딩이 되지 않기 때문에, 별도 커스텀 Behavior 또는 코드비하인드 연동이 필요합니다.


// 예시 (비추천이지만 필요한 경우)
treeView.SelectedItemChanged += (s, e) =>
{
    var selected = e.NewValue as Category;
    viewModel.SelectedCategory = selected;
};

6. 마무리 및 다음 글 예고

  • TreeView에서 MVVM 구조로 Command 바인딩 가능
  • Interaction 트리거 또는 Behavior SDK를 통해 이벤트 연결
  • RelayCommand와 ICommand 구현은 MVVM의 핵심

다음 시리즈에서는 TreeView와 ContextMenu(우클릭 메뉴) 및 동적 노드 추가/삭제를 실습해보겠습니다!
감사합니다 😊 질문은 언제든지 댓글로 남겨주세요!