| File: System\Windows\Input\Command\CommandBinding.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationCore\PresentationCore.csproj (PresentationCore) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // namespace System.Windows.Input { /// <summary> /// CommandBinding - Command-EventHandlers map /// CommandBinding acts like a map for EventHandlers and Commands. /// PreviewExecute/Execute, PreviewCanExecute/CanExecute handlers /// can be added at CommandBinding which will exist at Element level /// in the form of a Collection and will be invoked when the system /// is routing the corresponding RoutedEvents. /// </summary> public class CommandBinding { #region Constructors /// <summary> /// Default Constructor - required to allow creation from markup /// </summary> public CommandBinding() { } /// <summary> /// Constructor /// </summary> /// <param name="command">Command associated with this binding.</param> public CommandBinding(ICommand command) : this(command, null, null) { } /// <summary> /// Constructor /// </summary> /// <param name="command">Command associated with this binding.</param> /// <param name="executed">Handler associated with executing the command.</param> public CommandBinding(ICommand command, ExecutedRoutedEventHandler executed) : this(command, executed, null) { } /// <summary> /// Constructor /// </summary> /// <param name="command">Command associated with this binding.</param> /// <param name="executed">Handler associated with executing the command.</param> /// <param name="canExecute">Handler associated with determining if the command can execute.</param> public CommandBinding(ICommand command, ExecutedRoutedEventHandler executed, CanExecuteRoutedEventHandler canExecute) { ArgumentNullException.ThrowIfNull(command); _command = command; if (executed is not null) { Executed += executed; } if (canExecute is not null) { CanExecute += canExecute; } } #endregion #region Public Properties /// <summary> /// Command associated with this binding /// </summary> [Localizability(LocalizationCategory.NeverLocalize)] // cannot be localized public ICommand Command { get => _command; set { ArgumentNullException.ThrowIfNull(value); _command = value; } } #endregion #region Public Events /// <summary> /// Called before the command is executed. /// </summary> public event ExecutedRoutedEventHandler PreviewExecuted; /// <summary> /// Called when the command is executed. /// </summary> public event ExecutedRoutedEventHandler Executed; /// <summary> /// Called before determining if the command can be executed. /// </summary> public event CanExecuteRoutedEventHandler PreviewCanExecute; /// <summary> /// Called to determine if the command can be executed. /// </summary> public event CanExecuteRoutedEventHandler CanExecute; #endregion #region Implementation /// <summary> /// Calls the CanExecute or PreviewCanExecute event based on the event argument's RoutedEvent. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">Event arguments.</param> internal void OnCanExecute(object sender, CanExecuteRoutedEventArgs e) { if (e.Handled) return; if (e.RoutedEvent == CommandManager.CanExecuteEvent) { if (CanExecute is null) { if (e.CanExecute) return; // If there is an Executed handler, then the command can be executed. if (Executed is null) return; e.CanExecute = true; e.Handled = true; } else { CanExecute(sender, e); if (e.CanExecute) { e.Handled = true; } } } else // e.RoutedEvent == CommandManager.PreviewCanExecuteEvent { if (PreviewCanExecute is null) return; PreviewCanExecute(sender, e); if (e.CanExecute) { e.Handled = true; } } } private bool CheckCanExecute(object sender, ExecutedRoutedEventArgs e) { CanExecuteRoutedEventArgs canExecuteArgs = new(e.Command, e.Parameter) { RoutedEvent = CommandManager.CanExecuteEvent, // Since we don't actually raise this event, we have to explicitly set the source. Source = e.OriginalSource }; canExecuteArgs.OverrideSource(e.Source); OnCanExecute(sender, canExecuteArgs); return canExecuteArgs.CanExecute; } /// <summary> /// Calls Executed or PreviewExecuted based on the event argument's RoutedEvent. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">Event arguments.</param> internal void OnExecuted(object sender, ExecutedRoutedEventArgs e) { if (e.Handled) return; if (e.RoutedEvent == CommandManager.ExecutedEvent) { if (Executed is null) return; if (!CheckCanExecute(sender, e)) return; Debug.Assert(Executed != null, nameof(Executed) + " != null"); Executed(sender, e); e.Handled = true; } else // e.RoutedEvent == CommandManager.PreviewExecutedEvent { if (PreviewExecuted is null) return; if (!CheckCanExecute(sender, e)) return; Debug.Assert(PreviewExecuted != null, nameof(PreviewExecuted) + " != null"); PreviewExecuted(sender, e); e.Handled = true; } } #endregion #region Data private ICommand _command; #endregion } }