프로그래밍/c# wpf

WPF MVVM RelayCommand 사용법: ICommand 구현부터 활용까지 완벽 가이드

rrruu 2025. 6. 23. 11:03
반응형

RelayCommand란 무엇인가?

RelayCommand는 WPF의 ICommand 인터페이스를 구현하여 MVVM 패턴에서 ViewModel의 메서드를 View의 Command에 바인딩할 수 있도록 돕는 클래스입니다. 버튼 클릭, 메뉴 선택 등 UI 이벤트를 ViewModel로 깔끔하게 연결해 주며, 코드 비하인드(code-behind)를 최소화하여 유지보수성을 높입니다.

주요 특징:

  • 커맨드 실행 로직과 실행 가능 여부를 분리하여 관리
  • 매개변수(Parameter) 전달 지원
  • CanExecuteChanged 이벤트를 통해 UI 활성화/비활성화 자동 반영

RelayCommand 구현하기

1. RelayCommand 클래스 정의

/// <summary>
/// MVVM 패턴에서 사용하는 릴레이 커맨드 클래스
/// </summary>
public class RelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Predicate<object> _canExecute;

    /// <summary>
    /// RelayCommand 생성자
    /// </summary>
    /// <param name="execute">실행할 액션</param>
    /// <param name="canExecute">실행 가능 여부를 판단하는 조건 (선택사항)</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    /// <summary>
    /// 매개변수가 없는 RelayCommand 생성자
    /// </summary>
    /// <param name="execute">실행할 액션</param>
    /// <param name="canExecute">실행 가능 여부를 판단하는 조건 (선택사항)</param>
    public RelayCommand(Action execute, Func<bool> canExecute = null)
        : this(
            execute != null ? new Action<object>(_ => execute()) : null,
            canExecute != null ? new Predicate<object>(_ => canExecute()) : null)
    {
    }

    /// <summary>
    /// 커맨드 실행 가능 여부가 변경되었을 때 발생하는 이벤트
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    /// <summary>
    /// 커맨드 실행 가능 여부 확인
    /// </summary>
    /// <param name="parameter">커맨드 매개변수</param>
    /// <returns>실행 가능하면 true, 그렇지 않으면 false</returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute?.Invoke(parameter) ?? true;
    }

    /// <summary>
    /// 커맨드 실행
    /// </summary>
    /// <param name="parameter">커맨드 매개변수</param>
    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    /// <summary>
    /// CanExecute 상태 변경을 강제로 알림
    /// </summary>
    public void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }
}

2. ViewModel에서 RelayCommand 사용하기

ViewModel에서 명령(Command) 속성을 정의하고, 생성자에서 RelayCommand를 초기화합니다. 아래 예제는 버튼 클릭 시 텍스트를 변경하는 간단한 예입니다.

// MainViewModel.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;

public class MainViewModel : INotifyPropertyChanged
{
    // 버튼 클릭 시 메시지 박스 표시 커맨드
    public ICommand ShowMessageCmd => new RelayCommand(OnShowMessage, CanShowMessage);

    private void OnShowMessage(object obj)
    {
        MessageBox.Show("안녕하세요! RelayCommand 예제입니다.", "메시지");
    }

    private bool CanShowMessage(object obj)
    {
        // 항상 실행 가능하도록 true 반환
        return true;
    }

    public MainViewModel()
    {
        // 초기화 로직이 필요하다면 여기에 추가
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

3. View와 바인딩

XAML에서는 ViewModel을 DataContext로 설정한 뒤, Button의 Command 속성에 RelayCommand를 바인딩합니다.

<!-- MainWindow.xaml -->
<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RelayCommand 메시지 예제" Height="200" Width="400">
  <Window.DataContext>
    <local:MainViewModel />
  </Window.DataContext>
  <Grid Margin="20">
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
      <Button Content="메시지 표시"
              Command="{Binding ShowMessageCmd}"
              Width="120" Height="40"/>
    </StackPanel>
  </Grid>
</Window>

 

반응형