Files
2026-04-17 14:55:32 -04:00

4.1 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.Common/Classes/DTS.Viewer/Commands/RelayCommand.cs
2026-04-16T03:19:06.518329+00:00 Qwen/Qwen3-Coder-Next-FP8 1 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.