--- source_files: - Common/DTS.Common/Classes/DTS.Viewer/Commands/RelayCommand.cs generated_at: "2026-04-16T03:19:06.518329+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "33db5b96b73a6f00" --- # Commands ### 1. **Purpose** This module implements a concrete, reusable `ICommand`-based command class (`RelayCommand`) for WPF applications, enabling decoupling of UI actions (e.g., button clicks) from their execution logic. It supports optional conditional execution via a `CanExecute` predicate and integrates with WPF’s `CommandManager` to automatically re-evaluate command availability when UI state changes (e.g., focus or selection changes). Its role is to serve as a lightweight, standard command implementation for MVVM pattern adoption, avoiding boilerplate command classes per action. --- ### 2. **Public Interface** - **`RelayCommand(Action execute)`** Constructor. Initializes the command with an execution delegate and no `CanExecute` predicate (i.e., always executable). - Throws `ArgumentNullException` if `execute` is `null`. - **`RelayCommand(Action execute, Predicate canExecute)`** Constructor. Initializes the command with both execution and availability predicates. - Throws `ArgumentNullException` if `execute` is `null`. - `canExecute` may be `null`, in which case the command is always executable. - **`bool CanExecute(object parameter)`** Implements `ICommand.CanExecute`. Returns `true` if `_canExecute` is `null` or if `_canExecute(parameter)` returns `true`; otherwise `false`. - **`event EventHandler CanExecuteChanged`** Implements `ICommand.CanExecuteChanged`. Subscribes/unsubscribes to `CommandManager.RequerySuggested`, triggering WPF to re-query `CanExecute` when system events (e.g., keyboard/mouse input, focus changes) occur. - **`void Execute(object parameter)`** Implements `ICommand.Execute`. Invokes `_execute(parameter)`. No validation or exception handling is performed; exceptions propagate to the caller. --- ### 3. **Invariants** - `_execute` is **never `null`** after construction (enforced via `ArgumentNullException` in both constructors). - `_canExecute` may be `null`; in this case, `CanExecute` always returns `true`. - `CanExecuteChanged` events are **always** routed to `CommandManager.RequerySuggested`; no custom event storage is used. - `Execute` and `CanExecute` are called with the same `parameter` value provided by the command source (e.g., `Button.CommandParameter`). --- ### 4. **Dependencies** - **Dependencies on external modules**: - `System` (for `Action`, `Predicate`, `ArgumentNullException`) - `System.Windows.Input` (for `ICommand`, `CommandManager`) - **Dependencies on other modules in the codebase**: None (no internal `using` statements beyond standard libraries). - **Depended upon by**: Presumably UI components (e.g., `Button`, `MenuItem`) in WPF views that bind commands via MVVM. Not visible in this file, but inferred from `ICommand` usage. --- ### 5. **Gotchas** - **No manual `CanExecuteChanged` raising**: Since `CanExecuteChanged` is wired to `CommandManager.RequerySuggested`, the command’s executability is only re-evaluated on `CommandManager`-triggered events (e.g., user input). If the command’s availability depends on non-UI state (e.g., background task completion), `CommandManager.InvalidateRequerySuggested()` must be called externally to force re-evaluation. - **No parameter validation**: `Execute` passes the `parameter` directly to `_execute` without null-checking or type validation. If `_execute` expects a specific type (e.g., `string`), passing an incompatible type will cause a runtime exception. - **Thread affinity**: `Execute` runs on the calling thread (typically the UI thread), but no thread-safety guarantees are provided. If invoked from a background thread, UI updates inside `_execute` will fail. - **Memory leak risk**: If subscribers to `CanExecuteChanged` are not properly disposed, the `CommandManager` may hold references indefinitely (though this is a general WPF pattern risk, not unique to this class). None identified beyond the above.