Passing Context with CommandParameter
CommandParameter is a dependency property on ICommandSource controls that lets a View pass an arbitrary object into a command's Execute and CanExecute methods, most commonly used when a single command handles multiple instances of the same UI element, such as a Delete button repeated inside an ItemsControl's DataTemplate. Binding CommandParameter to '{Binding}' inside a DataTemplate passes the current data-bound item itself, so a DeleteItemCommand on the parent ViewModel receives exactly which item's Delete button was clicked, without needing a separate command per row.
Cricket analogy: It's like a single DRS review command used across every batter at the crease, the umpire's decision engine (Execute) is the same for everyone, but the specific batter under review is passed in as a parameter, just as CommandParameter identifies which row's data item to act on.
<ItemsControl ItemsSource="{Binding Tasks}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" Width="200"/>
<Button Content="Delete"
Command="{Binding DataContext.DeleteTaskCommand,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>Typed Parameters and Casting
Because CommandParameter is declared as object, a RelayCommand's Execute(object parameter) typically must cast it back to the expected type, for example '(TaskItem)parameter', which is fragile if the binding accidentally supplies the wrong type or null. Using a generic RelayCommand<TaskItem> avoids this by performing the cast once inside the command implementation itself, and it also short-circuits CanExecute to false automatically when the incoming parameter cannot be cast to TaskItem, preventing a common InvalidCastException at runtime.
Cricket analogy: It's like a scorer's ledger accepting any handwritten note (object) and having to interpret whether it's a run count or a wicket entry each time, versus a structured digital scoring app that only accepts pre-typed run entries, avoiding misread numbers.
Multi-Value Parameters
When a single command needs more than one contextual value, such as both the clicked item and a modifier key state, developers commonly use MultiBinding with an IMultiValueConverter to pack several bound values into a single Tuple or a small purpose-built struct passed as CommandParameter, since XAML's Command and CommandParameter properties only ever accept one bound value each. An alternative that avoids converters entirely is exposing a small composite object, like a SelectedItemContext record, directly from the ViewModel so the View only needs a single simple binding.
Cricket analogy: It's like a match report needing both the striker's name and the exact ball number for a wicket entry, so scorers bundle them into a single WicketEvent record rather than two separate loose fields passed independently.
For ListBox or DataGrid selections, binding CommandParameter to SelectedItem via '{Binding SelectedItem, RelativeSource={RelativeSource AncestorType=ListBox}}' is a common alternative to per-row bindings, useful when the command applies to whichever row is currently selected rather than a specific clicked row.
CommandParameter values from XAML bindings are boxed as object and are not converted like typed dependency properties; passing a string where an int is expected will not auto-convert and can cause an InvalidCastException inside Execute unless you defensively use 'as' casting or a typed RelayCommand<T>.
- CommandParameter passes a single object from the View into a command's Execute and CanExecute methods.
- Binding CommandParameter to '{Binding}' inside a DataTemplate passes the current row's data item.
- RelayCommand<T> avoids manual casting and automatically guards CanExecute against wrong-typed parameters.
- MultiBinding with IMultiValueConverter or a composite ViewModel object solves the multi-value parameter need.
- SelectedItem bindings are a common CommandParameter source for list and grid selection commands.
- CommandParameter values are boxed as object and are never auto-converted between types.
- Defensive casting or generic typed commands prevent runtime InvalidCastException bugs.
Practice what you learned
1. What does binding CommandParameter to '{Binding}' inside a DataTemplate pass to the command?
2. What advantage does RelayCommand<T> have over the non-generic RelayCommand regarding CommandParameter?
3. What is the standard XAML approach for passing more than one value as a single CommandParameter?
4. Why can passing a string CommandParameter into a command expecting an int cause a runtime error?
5. Which binding is a common way to pass the currently selected row of a DataGrid as CommandParameter?
Was this page helpful?
You May Also Like
The ICommand Interface
The core .NET interface that lets ViewModels expose actions to the View without any code-behind, forming the backbone of command-based interaction in MVVM.
The RelayCommand Pattern
A reusable ICommand implementation that wraps Execute and CanExecute delegates, eliminating the need to write a bespoke command class for every ViewModel action.
Command Binding in XAML
The XAML-side mechanics of wiring controls to ViewModel commands, covering Command, CommandParameter, CommandTarget, KeyBinding, and InputBinding-based invocation.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics