06.1 CommandParameter
RelayCommand는 MVVM 구조에서 메서드(Logic)를 실행하는 방법 입니다.
CommandParameter는 RelayCommand에 "매개변수"를 전달해 메서드(Logic)를 실행하는 방법 입니다.
1️⃣ CommandParameter 개요
📚 Microsoft Docs: CommunityToolkit.Mvvm.Input.RelayCommand
✅ CommandParameter 개요
- XAML에서 Button, MenuItem, ListBoxItem 등의 컨트롤이 명령(Command)을 실행할 수 있습니다.
CommandParameter는 이때 추가적인 데이터를 전달하는 속성입니다. - MVVM에서는 View와 ViewModel이 직접 연결되지 않도록 하기 위해,
이벤트 기반의 직접 호출 대신(Button Click 이벤트에서 sender를 사용할 수 없음) Command를 사용합니다.
Command는 기본적으로 매개변수를 받을 수 없습니다.
따라서 어떤 객체인지 ViewModel로 직접 전달하기 위해 CommandParameter가 중간 매개체 역할을 합니다.
✅ CommandParameter 동작 구조
[View, XAML]
Button → Command="{Binding SomeCommand}"
CommandParameter="{Binding Name}" />
↓ 클릭 시
[ViewModel]
void MyCommand(string name) { ... } 실행됨
✅ CommandParameter 사용 예시
구문 | 의미 |
CommandParameter="{Binding}" | 현재 DataContext 객체 전체 전달 |
CommandParameter="{Binding Name}" | 특정 속성만 전달 |
CommandParameter="정적 값" | 고정된 텍스트 또는 숫자 전달 |
CommandParameter="{Binding SelectedItem, ElementName=MyList}" | 다른 컨트롤 값 전달 |
Tuple, ValueTuple + Converter 사용 | 다중 값 전달 (MultiBinding) |
CommandParameter="{x:Null}" | 명시적으로 null 전달 |
2️⃣ 03CommandParameter - 예제
✔️ 1. 학습 목표
- Step 1.
- ViewModel에서 동작할 비지니스 로직에, 매개변수를 전달받아 동작되도록 구현합니다.
- Step 2.
- View에서 특정 속성값을 매개변수로 전달받습니다.
- Step 3.
- 전달받은 값을 ViewModel 메서드 실행시 반영되는지 확인합니다.
✔️ 2. 동작 시나리오

- TextBox에서 입력받은 값을
- 버튼을 누를때, 컨트롤에서 전달받은 값을 ViewModel 메서드에 전달하여
- View에 다시 반영되도록 합니다.
✔️ 2. [ RelayCommand ]으로 구현
📁 2.1 프로젝트 구조
WpfMvvmToolkit05_03CommandParameter/
├── ViewModels/
│ ├── MainViewModel.cs
└── Views/
├── MainWindow.xaml ← 메인 뷰
└── MainWindow.xaml.cs
📁 2.2 ViewModel 클래스 만들기 (MainViewModel.cs)
public partial class MainViewModel : ObservableObject
{
// 사용자 이름 입력
[ObservableProperty]
private string? userName;
// 인사 메시지 출력 결과
[ObservableProperty]
private string? greeting;
// CommandParameter로 이름을 전달받아 인사 메시지를 설정하는 커맨드
[RelayCommand]
private void Greet(string name)
{
Greeting = $"안녕하세요, {name}님!";
Debug.WriteLine(Greeting);
}
}
📁 2.4 XAML 화면 구성
xmlns:vm="clr-namespace:WpfMvvmToolkit05_03CommandParameter.ViewModels"
Title="GreetCommand Demo" Height="200" Width="300">
<Window.DataContext>
<vm:MainViewModel />
</Window.DataContext>
<StackPanel Margin="20">
<!-- 사용자 이름 입력 -->
<TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}" Margin="0 0 0 10" />
<!-- 이름을 파라미터로 전달하여 인사 메시지 출력 -->
<Button Content="인사하기"
Command="{Binding GreetCommand}"
CommandParameter="{Binding UserName}" />
<!-- 인사 결과 출력 -->
<TextBlock Text="{Binding Greeting}" FontSize="16" Margin="10 0 0 0"/>
</StackPanel>
3️⃣ 04CommandParameter - 예제
✔️ 1. 동작 시나리오

- 버튼 컨트롤에서 전달받은 값(이름)을 전달받아
- RelayCommand 에 전달
- 콘솔 출력
✔️ 2. [ RelayCommand ]으로 구현
📁 2.1 프로젝트 구조
WpfMvvmToolkit04_RelayCommand02_Prams/
├── Models/
│ └── User.cs
├── ViewModels/
│ ├── MainViewModel.cs
├── Views/
│ ├── MainWindow.xaml ← 메인 뷰
│ ├── MainWindow.xaml.cs
└── App.xaml
└── App.xaml.cs
🔍 2.2 Model 클래스 만들기
// User 클래스는 MVVM 아키텍처에서 Model 역할을 수행합니다.
// 이 클래스는 사용자 데이터를 표현하며, ViewModel과 Service에서 데이터를 주고받는 데 사용됩니다.
public class User
{
// 사용자 이름을 저장하는 속성입니다.
// 기본값은 빈 문자열로 초기화되어 있으며, 비어 있는 상태에서도 안전하게 사용 가능합니다.
public string Name { get; set; } = string.Empty;
}
🔍 2.3 ViewModel 클래스 만들기 (MainViewModel.cs)
// MainViewModel 클래스는 MVVM 패턴에서 View와 Model 사이의 중개자 역할을 수행합니다.
// ObservableObject를 상속받아 INotifyPropertyChanged를 자동으로 구현하며,
// UI와 데이터 간의 바인딩이 실시간으로 동작하도록 지원합니다.
public partial class MainViewModel : ObservableObject
{
// Users는 사용자 목록을 보관하는 ObservableCollection입니다.
// ObservableCollection은 UI와 자동 동기화되며, ItemsControl 등과 바인딩할 때 자주 사용됩니다.
public ObservableCollection<User> Users { get; } = new()
{
new User { Name = "홍길동" },
new User { Name = "김철수" },
new User { Name = "이영희" }
};
// GreetUser 명령은 XAML에서 Button의 Command와 바인딩됩니다.
// 이 명령은 CommandParameter로 User 객체를 전달받아 처리할 수 있습니다.
// CommunityToolkit.MVVM의 [RelayCommand] 특성을 사용하면 GreetUserCommand 속성이 자동 생성됩니다.
[RelayCommand]
private void GreetUser(User user)
{
// 전달받은 User 객체의 이름을 출력합니다.
// 실습 환경에서는 콘솔 출력으로 확인하며, 실제 앱에서는 메시지 박스, 로그, 뷰에 바인딩된 속성 등으로 확장할 수 있습니다.
Console.WriteLine($"Hello {user.Name}!");
}
}
🔍 2.4 XAML 화면 구성
Title="Greet Users" Height="300" Width="300">
<!-- MainViewModel을 현재 View의 데이터 컨텍스트로 설정하여 ViewModel의 속성과 명령을 바인딩할 수 있게 합니다. -->
<Window.DataContext>
<vm:MainViewModel />
</Window.DataContext>
<StackPanel Margin="10">
<!-- Users 컬렉션을 ItemsSource로 설정하여 사용자 목록을 동적으로 생성합니다. -->
<ItemsControl ItemsSource="{Binding Users}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- 각 User 항목을 수평으로 정렬하는 StackPanel로 구성합니다. -->
<StackPanel Orientation="Horizontal" Margin="5">
<!-- 사용자 이름을 출력하는 TextBlock입니다. -->
<TextBlock Text="{Binding Name}" Width="100"/>
<!--사용자별 인사 버튼입니다.
Command: MainViewModel의 GreetUserCommand에 바인딩합니다.
RelativeSource를 통해 상위(Window)의 DataContext에서 명령을 찾습니다.
CommandParameter: 현재 항목(User 객체 전체)을 매개변수로 전달합니다.
결과적으로 버튼 클릭 시 해당 User 객체가 GreetUser(User user) 메서드에 전달됩니다.-->
<Button Content="인사하기"
Command="{Binding DataContext.GreetUserCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
✔️ 2.5 결과
- 버튼을 클릭하면 해당 이름이 콘솔에 출력
4️⃣ 05CommandParameter="{Binding}" - 예제
✔️ 1. 예제의 ItemConrtol 살펴보기 (ListBox 등 동일)
<ItemsControl ItemsSource="{Binding Users}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="5">
<TextBlock Text="{Binding Name}" Width="100"/>
<Button Content="인사하기"
Command="{Binding DataContext.GreetUserCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
✔️ 1.1 ItemTemplate → DataTemplate 간략 예시
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<Button Command="{Binding DataContext.GreetUserCommand}",
CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
*ItemTemplate 내부에는 하나의 Person 객체가 바인딩 됨
✔️ 1.2 CommandParameter="{Binding}"
ListBox → People 컬렉션 바인딩
└ ItemTemplate의 DataContext = 각 Person 객체를 바인딩
└ Button.CommandParameter = 바인딩된 각 Person 객체 데이터
- 현재 DataContext 객체 전체 전달
- ItemTemplate 내의 DataContext, 즉 하나의 Person 객체
✔️ 1.3 Command="{Binding DataContext.GreetUserCommand}"
[RelayCommand]
private void GreetUser(User user) // 바로 이 부분의 파라미터에 전달!
{
Debug.WriteLine($"Hello {user.Name}!");
}
✔️ 1.4 CommandParameter 전달 구조
[ListBox]
├── Person { Name = "홍길동" }
│ └── Button → CommandParameter = Person("홍길동") → GreetUser(Person("홍길동"))
├── Person { Name = "김철수" }
│ └── Button → CommandParameter = Person("김철수") → GreetUser(Person("김철수"))
└── Person { Name = "이영희" }
└── Button → CommandParameter = Person("이영희") → GreetUser(Person("이영희"))
✔️ 2. 참고
✔️ 3. 참고
- {Binding}을 생략하면, Command는 실행되지만 person 파라미터는 null 이 됩니다.
- CommandParameter="{Binding Name}" 과 같이 사용하시면,
메서드 시그니처도 ShowPerson(string name)처럼 변경합니다.
4️⃣ RelativeSource={RelativeSource AncestorType=Window} 사용 이유
* ListBox, DataGrid, ComboBox 등의 ItemTemplate 내부 Command 바인딩 시 필수
✔️ 1. 예제의 ItemConrtol 살펴보기 (ListBox 등 동일)
<ItemsControl ItemsSource="{Binding Users}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="5">
<TextBlock Text="{Binding Name}" Width="100"/>
<Button Content="인사하기"
Command="{Binding DataContext.GreetUserCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
✔️ 1.1 ItemTemplate → DataTemplate → Button 간략 예시
<Button Content="인사하기"
Command="{Binding DataContext.GreetUserCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}" />
- Command=...는 ViewModel에 있는 ShowPersonCommand를 찾아야 하지만
이 버튼은 ListBox.ItemTemplate 내부에 있어서, 기본적으로 Person을 DataContext로 바라보고 있음 - CommandParameter="{Binding}"는 여전히 Person 객체 → 즉 항목 자체만 접근 가능
그래서 RelativeSource를 써서 Window의 DataContext(ViewModel)에서 접근함
✔️ 1.2 RelativeSource={RelativeSource AncestorType=Window}
[Window]
└── DataContext = MainViewModel
└── ShowPersonCommand ⬅ 이걸 찾기 위해 RelativeSource 사용
[ListBox ItemsSource=People]
├── ItemTemplate
│ └── DataContext = Person ("홍길동", "김철수" 등)
│ └── Button.Command = MainViewModel.ShowPersonCommand ⬅ 이걸 찾기 위해 RelativeSource 사용
│ └── Button.CommandParameter = 해당 Person ("홍길동", "김철수" 등) 객체
구성 | 설명 |
RelativeSource | 바인딩 기준을 상대적으로 설정함 |
AncestorType=Window | Button의 부모 계층을 타고 올라가면서 가장 가까운 Window를 찾음 |
DataContext.____Command | 그 Window의 DataContext(ViewModel)에 있는 명령을 사용하겠다는 의미 |
✔️ 1.3 대안 - ElementName 바인딩 (명시적 이름 바인딩)
<Window x:Name="MainWin">
<Button Command="{Binding DataContext.SomeCommand, ElementName=MainWin}" />
</Window>
* UI 요소의 이름을 기준으로 바인딩
5️⃣ 참고
- {Binding}을 생략하면, Command는 실행되지만 person 파라미터는 null 이 됩니다.
- CommandParameter="{Binding Name}" 과 같이 사용하시면,
메서드 시그니처도 ShowPerson(string name)처럼 변경합니다.