This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
---
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 WPFs `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<object> 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<object> execute, Predicate<object> 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<T>`, `Predicate<T>`, `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 commands executability is only re-evaluated on `CommandManager`-triggered events (e.g., user input). If the commands 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.