RelayCommand는 MVVM 구조에서 메서드(Logic)를 실행하는 방법 입니다.
CommandParameter는 RelayCommand에 "매개변수"를 전달해 메서드(Logic)를 실행하는 방법 입니다.

 

1️⃣ RelayCommand<T> 개요

더보기

📚  Microsoft Docs: RelayCommand<T> Generator

 

 

✔️ RelayCommand<T> 개요

  • RelayCommand<T>는
    View에서  ViewModel 메서드를 실행해야 할 때, 매개변수를 전달 하기 위해 사용합니다.
  • CommandParameter는
    전달되는 인자의 타입을 명확히 지정할 수 있는 제네릭 버전의 명령(Command)입니다.

 

 

✔️ 왜 필요한가?

  1. CommandParameter="{Binding}"로 객체를 전달할 때,
  2. object로 받으면 명시적 형변환(cast) 필요합니다. 이는 런타임 오류 발생 가능성이 존재합니다.
  3. RelayCommand<T>로 받으면 컴파일 타임에 타입 검증이 가능하여 안전합니다.



✔️  관련 네임스페이스

using CommunityToolkit.Mvvm.Input;



✔️  소스코드

 

WpfMvvmToolkit.zip
0.82MB

 

2️⃣ 01RelayCommand - 매개변수 없는, 간단한 RelayCommand 구현 예제

더보기

*CommunityToolkit.Mvvm 패키지 설치 후 진행해주세요.

 

✔️ 1. 동작 시나리오

  1. 사용자가 버튼을 클릭하면 HelloCommand가 실행되고 메시지 박스 출력

 

 

✔️ 2. RelayCommand 로 구현

 

📁 2.1 프로젝트 구조

RelayCommandDemo/
├── ViewModels/
│   └── MainViewModel.cs
├── MainWindow.xaml
└── MainWindow.xaml.cs

 

📁 2.2 ViewModel 클래스 만들기 (MainViewModel.cs)

public partial class MainViewModel : ObservableObject
{
    [RelayCommand]
    private void SayHello()
    {
        MessageBox.Show("안녕하세요! RelayCommand 버튼을 클릭했습니다.");
    }
}

 

📁 2.3 XAML 화면 구성

    xmlns:viewModels="clr-namespace:WPF_ToolKit09_01.ViewModels"
    Title="RelayCommand Demo" Height="200" Width="300">
<Window.DataContext>
    <viewModels:MainViewModel/>
</Window.DataContext>

<StackPanel Margin="20">
    <Button Content="Say Hello"
            Command="{Binding SayHelloCommand}"/>
</StackPanel>

 

 

✔️ 3. 결과

  • 버튼을 클릭하면 SayHello() 메서드가 실행되어 메시지박스 출력


3️⃣
02
ICommandParameter - 자동완성 없이, C# MVVM 구현 구조 예제 

더보기

✔️ 1. 학습 목표

 

  • Step 1. 
    • CommunityToolkit.Mvvm 패키지를 통한 자동완성 기능을 학습하기에 앞서,
      전통적인 방식의 C# MVVM 패턴 구현 방법을 되짚어 봅니다.
    • ICommand 인터페이스를 상속 구현한 RelayCommand 구현하고,
      ViewModel 에서 메서드에 매개변수를 전달하는 방법을 되짚어봅니다.
  • Step 2.
    • 이후에 CommunityToolkit.Mvvm 패키지를 사용해 자동 구현할 때,
      어떤 부분이 자동화되어 편리한지 확인합니다.
  • Step 3.
    • 그리고 프로젝트의 어느 부분에 적용하면 효과적일지 예상해봅니다.

 

 

 

 

✔️ 2. 동작 시나리오

1. 사용자가 TextBox에 이름 입력
   ↓
2. 버튼 클릭 → Command 실행
   ↓
3. CommandParameter 값 전달
   ↓
4. ViewModel 메서드에서 전달된 값 사용

// 이전 예제에서는, 두개의 프로퍼티를 사용해 View에 반영했습니다.

 

 

 

✔️ 3. 자동완성 없이, 전통적인 방식으로  C# MVVM 구조를 만들기 위해 ICommand  구현

 

📁 3.1 가장먼저, 아래 링크를 참고해 WPF 프로젝트를 생성 합니다.

 

WPF 프로젝트 생성하기

01. Visual Studio 실행더보기 02. 새 프로젝트 생성더보기❶ 최근 실행한 프로젝트의 목록을 보여줍니다.❷ GitHub, Azure, DevOps, Bitbucket 등 원격 저장소에서 프로젝트를 가져옵니다.❸ 내 컴퓨터의 로컬

basiclike.tistory.com

 

 

📁 3.2 생성한 WPF 프로젝트에, 아래 링크를 참고해 CommunityToolkit.Mvvm 패키지를 설치합니다.

 

02. 패키지 설치 방법

1️⃣ "NuGet 패키지 관리자"에서, CommunityToolkit.Mvvm 설치하는 방법더보기 WPF 프로젝트 생성하기01. Visual Studio 실행더보기 02. 새 프로젝트 생성더보기❶ 최근 실행한 프로젝트의 목록을 보여줍니다.

basiclike.tistory.com

 

 

📁 3.3 프로젝트 구조

WpfMvvmToolkit05_01ICommand/
├── Commands/
│   └── RelayCommand.cs
├── ViewModels/
│   └── MainViewModel.cs         
└── Views/
    └── MainWindow.xaml          ← 메인 뷰
    └── MainWindow.xaml.cs

 


📁 3.4 ICommandParameter 동작 구조

ViewModel 네임스페이스를 View에 등록합니다. DataContext를 지정합니다.

 

View에서 버튼을 클릭하면 바인딩 된 RelayCommand가 실행됩니다. 

 RelayCommand는, MainViewModel 생성시  SayHello(Object params) 메서드가 등록되도록 구현되어 

 RelayCommand가 실행되면, 등록된 SayHello(Object params) 메서드가 동작합니다.

 

 

📁 3.5 ICommand 구현

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


    public RelayCommand(Action<object?> execute)
    {
        this._execute = execute;
    }

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

    //.NET의 명시적 델리게이트 호출 메서드 .Invoke()를 사용가능하지만, 생략 사용 권장됨.
    //public void Execute(object? parameter) => _execute.Invoke(parameter);
    
    public void Execute(object? parameter) => _execute(parameter); // ← 가장 간결하고 일반적인 방식


    public event EventHandler? CanExecuteChanged;
}

 


📁 3.6 ViewModel 구현하기

public class MainViewModel : INotifyPropertyChanged
{
    private string? greeting;
    public string? Greeting
    {
        get => greeting;
        set
        {
            if (greeting != value)
            {
                greeting = value;
                OnPropertyChanged();
            }
        }
    }

    public ICommand SayHelloCommand { get; }

    public MainViewModel()
    {
        // CommandParameter 값을 받을 수 있는 명령 초기화
        SayHelloCommand = new RelayCommand(SayHello);
    }

    private void SayHello(object? parameter)
    {
        // parameter는 버튼 클릭 시 전달된 CommandParameter입니다.
        // parameter가 string 타입이면 true이고, 그 값을 name 변수에 담음
        if (parameter is string name && !string.IsNullOrWhiteSpace(name))
            Greeting = $"안녕하세요, {name}님!";
        else
            Greeting = "이름을 입력하세요!";
    }

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

 

 

📁 3.7 View 구성하기

    xmlns:vm="clr-namespace:WpfMvvmToolkit05_01ICommand.ViewModels"
    Title="RelayCommand Demo" Height="200" Width="300">

<Window.DataContext>
    <vm:MainViewModel />
</Window.DataContext>

<StackPanel Margin="20">
    <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"  
             Margin="0,0,0,10"/>

    <Button Content="인사하기" 
            Command="{Binding SayHelloCommand}" 
            Margin="0,0,0,10"/>

    <TextBlock Text="{Binding GreetingMessage}" 
               FontWeight="Bold" />
</StackPanel>


 03. RelayCommandGeneric - RelayCommand <T> 사용 구조 예제

더보기

*CommunityToolkit.Mvvm 패키지 설치 후 진행해 주세요.

 

 

✔️ 1. 학습 목표

  • " 매개변수 없는, 간단한 RelayCommand 구현 예제 " 및 이전 예들과 비교하여
    사용할 때, 어떤 부분을 효과적으로 사용 할 수 있는지 확인합니다.
// PersonViewModel 클래스는 MVVM 패턴에서 ViewModel 역할을 수행합니다.
// ObservableObject를 상속받아 INotifyPropertyChanged를 자동으로 구현합니다.
using CommunityToolkit.Mvvm.ComponentModel;

public partial class PersonViewModel : ObservableObject
{
    // private 필드(name)에 대해 자동으로 public 프로퍼티(Name)이 생성됩니다.
    // 또한 프로퍼니가 변경될 때 INotifyPropertyChanged 인터페이스를 통해 UI에 반영되도록 합니다.
    [ObservableProperty]
    private string? name;
}

 

 

 

✔️ 동작 시나리오

 

  1. 텍스트 박스에 이름을 입력하고
  2. 버튼을 클릭하면
  3. "_ _ _님, 안녕하세요!" 메시지 출력


✔️ 2. RelayCommand 로 구현

 

📁 2.1 프로젝트 구조

RelayCommandDemo/
├── ViewModels/
│   └── MainViewModel.cs
├── MainWindow.xaml
└── MainWindow.xaml.cs

 


📁2.2 ViewModel 클래스 만들기 (MainViewModel.cs)

public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private string userName;

    [RelayCommand]
    private void Greet(string name)
    {
        MessageBox.Show($"{name}님, 안녕하세요!");
    }
}


📁 
2.3 
XAML 화면 구성

    xmlns:viewModels="clr-namespace:WPF_ToolKit09_02.ViewModel"
    Title="RelayCommand&lt;T&gt; Demo" Height="200" Width="300">
<Window.DataContext>
    <viewModels:MainViewModel/>
</Window.DataContext>

<StackPanel Margin="20">
    <TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}" />
    <Button Content="Greet"
        Command="{Binding GreetCommand}"
        CommandParameter="{Binding UserName}"/>
</StackPanel>



✔️ 3. 결과

  • TextBox에 "홍길동" 입력 후 버튼 클릭 시, "홍길동님, 안녕하세요!" 출력

 

 

✔️ 비교 RelayCommand vs RelayCommand<T>

항목 RelayCommand RelayCommand<T>
매개변수 없음 있음
사용 예 단순 버튼 처리 입력값 전달, 리스트 항목 선택
XAML CommandParameter 필요 없음 필수 (값 바인딩)

 

 

 

4️⃣ 예제 - RelayCommand<T> 동작 구조

더보기

✔️ 1. 예제의  RelayCommand<T> 살펴보기

public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private string userName;

    [RelayCommand]
    private void Greet(string name)
    {
        MessageBox.Show($"{name}님, 안녕하세요!");
    }
}

 

 

✔️ 2. 자동 생성되는 코드

위처럼 작성하면 GreetCommand가 GreetCommand<String>으로 자동 생성됩니다.
이건 곧 IRelayCommand<String>를 통해 String 타입의 매개변수만 허용하는 명령이 됩니다.

 

 

✔️3. 작동 흐름

<Button Content="Greet"
    Command="{Binding GreetCommand}"
    CommandParameter="{Binding UserName}"/>
  1. (사용자가 TextBox에 이름 입력 → UserName 속성 업데이트)
  2. 사용자가 버튼을 클릭
  3. UserName 프로퍼티를 CommandParameter로
  4. ViewModel의 GreetCommand에 전달
  5. GreetCommand.Execute(UserName) → Greet(string name) 실행

 

 

 

 

✔️4. 추가 과제

  • 객체 전달
  • Person 객체를 매개변수로 전달하고, 로직에서 Name, Age 등 필드 사용

 

 

 


5️⃣ 예제 - IMultiValueConverter 복합 값 전달

더보기

✔️ ViewModel

[RelayCommand]
private void Submit((Person person, string comment) input)
{
    var (person, comment) = input;
    // 복합 정보 사용
}

 

✔️ View (XAML)

<Button Content="제출">
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource TupleConverter}">
            <Binding Path="." />
            <Binding Path="CommentText" />
        </MultiBinding>
    </Button.CommandParameter>
</Button>