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

4.2 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.CommonCore/Classes/DTS.Viewer/Commands/RelayCommand.cs
2026-04-16T02:42:33.604683+00:00 Qwen/Qwen3-Coder-Next-FP8 1 63672ade54ed35d0

Commands

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 serves as a lightweight command adapter that forwards Execute and CanExecute calls to user-provided delegates, supporting both mandatory execution logic and optional, parameterized execution guards. This pattern is foundational for implementing MVVM-style command binding in WPF.


Public Interface

All members are public and part of the RelayCommand class.

  • RelayCommand(Action<object> execute)
    Constructor. Initializes the command with an execution delegate and no CanExecute guard (i.e., CanExecute always returns true). Throws ArgumentNullException if execute is null.

  • RelayCommand(Action<object> execute, Predicate<object> canExecute)
    Constructor. Initializes the command with both execution and guard delegates. Throws ArgumentNullException if execute is null. The canExecute parameter may be null, in which case CanExecute defaults to true.

  • bool CanExecute(object parameter)
    Implements ICommand.CanExecute. Invokes the stored _canExecute predicate (if non-null) with parameter; otherwise returns true.

  • void Execute(object parameter)
    Implements ICommand.Execute. Invokes the stored _execute action with parameter. No validation is performed on parameter beyond null-safety of the delegate itself.

  • event EventHandler CanExecuteChanged
    Implements ICommand.CanExecuteChanged. Subscribes/unsubscribes to CommandManager.RequerySuggested, enabling automatic re-evaluation of CanExecute when WPF detects relevant state changes (e.g., keyboard/mouse input, focus changes).


Invariants

  • _execute is never null after construction (enforced via ArgumentNullException in both constructors).
  • _canExecute may be null; if so, CanExecute always returns true.
  • CanExecuteChanged event handlers are always attached to CommandManager.RequerySuggested, ensuring WPFs command system triggers requery logic.
  • No explicit validation is performed on the parameter passed to Execute or CanExecute; nulls are passed directly to the delegates.

Dependencies

  • External Dependencies:
    • System (for Action<T>, Predicate<T>, ArgumentNullException)
    • System.Windows.Input (for ICommand, CommandManager)
  • Internal Dependencies:
    • No other modules in the codebase are referenced (self-contained).
  • Depended Upon:
    • Likely consumed by WPF UI layers (e.g., Button.Command bindings) and view models throughout the DTS.Viewer subsystem.

Gotchas

  • No manual CanExecuteChanged raising: The class relies solely on CommandManager.RequerySuggested to trigger CanExecute re-evaluation. If the commands executability depends on non-UI state changes (e.g., background thread updates), callers must manually invoke CommandManager.InvalidateRequerySuggested() (or similar) to force updates.
  • Parameter handling: The parameter passed to Execute/CanExecute is unvalidated. Passing null is permitted and will be forwarded to the delegates—consumers must handle null parameters explicitly if needed.
  • Thread affinity: CommandManager.RequerySuggested is raised on the UI thread. If CanExecute delegates access non-UI-thread resources, thread-safety must be ensured by the caller.
  • No disposal pattern: The class does not implement IDisposable, and event subscriptions (via CanExecuteChanged) are not explicitly cleaned up—relying on WPFs lifetime management. This is acceptable for typical view model lifetimes but may cause leaks in long-lived command instances.
  • No async support: Execute is synchronous; asynchronous operations require manual wrapping (e.g., async void or fire-and-forget), which is error-prone.