handling-wpf-input-commands
SKILL.md
WPF Input and Commands Patterns
Handling user input and implementing command patterns in WPF applications.
1. Command System Overview
ICommand (Interface)
├── RoutedCommand (WPF built-in)
│ ├── ApplicationCommands (Copy, Paste, Cut, etc.)
│ ├── NavigationCommands (BrowseBack, BrowseForward, etc.)
│ ├── MediaCommands (Play, Pause, Stop, etc.)
│ └── EditingCommands (ToggleBold, ToggleItalic, etc.)
└── RelayCommand / DelegateCommand (MVVM)
2. Built-in Commands
2.1 ApplicationCommands
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Copy"
Executed="CopyCommand_Executed"
CanExecute="CopyCommand_CanExecute"/>
<CommandBinding Command="ApplicationCommands.Paste"
Executed="PasteCommand_Executed"/>
</Window.CommandBindings>
<StackPanel>
<Button Command="ApplicationCommands.Copy" Content="Copy (Ctrl+C)"/>
<Button Command="ApplicationCommands.Paste" Content="Paste (Ctrl+V)"/>
<Button Command="ApplicationCommands.Undo" Content="Undo (Ctrl+Z)"/>
<Button Command="ApplicationCommands.Redo" Content="Redo (Ctrl+Y)"/>
</StackPanel>
private void CopyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Copy logic
Clipboard.SetText(SelectedText);
}
private void CopyCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// Enable condition
e.CanExecute = !string.IsNullOrEmpty(SelectedText);
}
2.2 Common Built-in Commands
| Category | Commands |
|---|---|
| ApplicationCommands | New, Open, Save, SaveAs, Close, Print, Copy, Cut, Paste, Undo, Redo, Find, Replace, SelectAll, Delete, Properties, Help |
| NavigationCommands | BrowseBack, BrowseForward, BrowseHome, BrowseStop, Refresh, Favorites, Search, GoToPage, NextPage, PreviousPage, FirstPage, LastPage |
| MediaCommands | Play, Pause, Stop, Record, NextTrack, PreviousTrack, FastForward, Rewind, ChannelUp, ChannelDown, TogglePlayPause, IncreaseVolume, DecreaseVolume, MuteVolume |
| EditingCommands | ToggleBold, ToggleItalic, ToggleUnderline, IncreaseFontSize, DecreaseFontSize, AlignLeft, AlignCenter, AlignRight, AlignJustify |
3. Custom RoutedCommand
3.1 Define Custom Command
namespace MyApp.Commands;
using System.Windows.Input;
public static class CustomCommands
{
// Define custom command
public static readonly RoutedCommand RefreshData = new(
nameof(RefreshData),
typeof(CustomCommands),
new InputGestureCollection
{
new KeyGesture(Key.F5),
new KeyGesture(Key.R, ModifierKeys.Control)
});
public static readonly RoutedCommand ExportToPdf = new(
nameof(ExportToPdf),
typeof(CustomCommands),
new InputGestureCollection
{
new KeyGesture(Key.E, ModifierKeys.Control | ModifierKeys.Shift)
});
public static readonly RoutedCommand ToggleFullScreen = new(
nameof(ToggleFullScreen),
typeof(CustomCommands),
new InputGestureCollection
{
new KeyGesture(Key.F11)
});
}
3.2 Use Custom Command in XAML
<Window xmlns:cmd="clr-namespace:MyApp.Commands">
<Window.CommandBindings>
<CommandBinding Command="{x:Static cmd:CustomCommands.RefreshData}"
Executed="RefreshData_Executed"
CanExecute="RefreshData_CanExecute"/>
<CommandBinding Command="{x:Static cmd:CustomCommands.ExportToPdf}"
Executed="ExportToPdf_Executed"/>
</Window.CommandBindings>
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_Refresh"
Command="{x:Static cmd:CustomCommands.RefreshData}"
InputGestureText="F5"/>
<MenuItem Header="_Export to PDF"
Command="{x:Static cmd:CustomCommands.ExportToPdf}"
InputGestureText="Ctrl+Shift+E"/>
</MenuItem>
</Menu>
</Window>
4. InputBinding (Keyboard/Mouse Shortcuts)
4.1 KeyBinding
<Window.InputBindings>
<!-- Keyboard shortcut -->
<KeyBinding Key="N" Modifiers="Control" Command="ApplicationCommands.New"/>
<KeyBinding Key="S" Modifiers="Control" Command="ApplicationCommands.Save"/>
<KeyBinding Key="S" Modifiers="Control+Shift" Command="ApplicationCommands.SaveAs"/>
<KeyBinding Key="F4" Modifiers="Alt" Command="ApplicationCommands.Close"/>
<!-- Function keys -->
<KeyBinding Key="F1" Command="ApplicationCommands.Help"/>
<KeyBinding Key="F5" Command="{x:Static cmd:CustomCommands.RefreshData}"/>
<!-- MVVM Command binding -->
<KeyBinding Key="Delete" Command="{Binding DeleteCommand}"/>
</Window.InputBindings>
4.2 MouseBinding
<Border.InputBindings>
<!-- Double-click -->
<MouseBinding MouseAction="LeftDoubleClick"
Command="{Binding OpenDetailCommand}"/>
<!-- Middle click -->
<MouseBinding MouseAction="MiddleClick"
Command="{Binding CloseTabCommand}"/>
<!-- Ctrl + Left click -->
<MouseBinding MouseAction="LeftClick"
Modifiers="Control"
Command="{Binding MultiSelectCommand}"/>
</Border.InputBindings>
5. CommandParameter
5.1 Static Parameter
<Button Command="{Binding NavigateCommand}"
CommandParameter="Home"
Content="Go to Home"/>
<Button Command="{Binding SetZoomCommand}"
CommandParameter="100"
Content="Zoom 100%"/>
5.2 Binding Parameter
<ListBox x:Name="ItemList" ItemsSource="{Binding Items}"/>
<Button Command="{Binding DeleteCommand}"
CommandParameter="{Binding SelectedItem, ElementName=ItemList}"
Content="Delete Selected"/>
<!-- Self-reference -->
<Button Command="{Binding ProcessCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Content="Process This Button"/>
6. CommandTarget
6.1 Redirecting Command Target
<StackPanel>
<TextBox x:Name="TargetTextBox"/>
<!-- Commands target the TextBox even when button is focused -->
<Button Command="ApplicationCommands.Copy"
CommandTarget="{Binding ElementName=TargetTextBox}"
Content="Copy from TextBox"/>
<Button Command="ApplicationCommands.Paste"
CommandTarget="{Binding ElementName=TargetTextBox}"
Content="Paste to TextBox"/>
</StackPanel>
7. Handling Keyboard Input
7.1 Key Events
namespace MyApp.Views;
using System.Windows;
using System.Windows.Input;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Preview events (Tunneling - captured before child elements)
PreviewKeyDown += OnPreviewKeyDown;
// Normal events (Bubbling - captured after child elements)
KeyDown += OnKeyDown;
}
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
// Global shortcut handling
if (e.Key == Key.Escape)
{
// Close popup or cancel operation
e.Handled = true;
}
// Modifier key combinations
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.G)
{
// Ctrl+G: Go to line
ShowGoToLineDialog();
e.Handled = true;
}
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
// Handle if not processed by child elements
}
}
7.2 TextInput Event
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
// Allow only numeric input
if (!char.IsDigit(e.Text, 0))
{
e.Handled = true;
}
}
8. Handling Mouse Input
8.1 Mouse Events
namespace MyApp.Controls;
using System.Windows;
using System.Windows.Input;
public partial class DrawingCanvas : FrameworkElement
{
private Point _startPoint;
private bool _isDragging;
public DrawingCanvas()
{
MouseLeftButtonDown += OnMouseLeftButtonDown;
MouseMove += OnMouseMove;
MouseLeftButtonUp += OnMouseLeftButtonUp;
MouseWheel += OnMouseWheel;
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(this);
_isDragging = true;
// Capture mouse to receive events outside the element
CaptureMouse();
// Click count detection
if (e.ClickCount == 2)
{
// Double click
}
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (!_isDragging) return;
var currentPoint = e.GetPosition(this);
var delta = currentPoint - _startPoint;
// Draw or drag logic
}
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_isDragging)
{
_isDragging = false;
ReleaseMouseCapture();
}
}
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
// e.Delta: positive = scroll up, negative = scroll down
var zoomFactor = e.Delta > 0 ? 1.1 : 0.9;
ApplyZoom(zoomFactor);
}
}
9. Focus Management
9.1 Programmatic Focus Control
// Set focus
myTextBox.Focus();
// Set keyboard focus specifically
Keyboard.Focus(myTextBox);
// Check focus
if (myTextBox.IsFocused)
{
// Has focus
}
if (myTextBox.IsKeyboardFocused)
{
// Has keyboard focus
}
9.2 FocusManager
<!-- Set default focused element -->
<Window FocusManager.FocusedElement="{Binding ElementName=FirstTextBox}">
<StackPanel>
<TextBox x:Name="FirstTextBox"/>
<TextBox x:Name="SecondTextBox"/>
</StackPanel>
</Window>
<!-- Define focus scope -->
<ToolBar FocusManager.IsFocusScope="True">
<Button Content="Button 1"/>
<Button Content="Button 2"/>
</ToolBar>
10. References
Weekly Installs
3
Repository
christian289/do…audecodeGitHub Stars
16
First Seen
Feb 28, 2026
Security Audits
Installed on
gemini-cli3
opencode3
codebuddy3
github-copilot3
codex3
kimi-cli3