|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Windows.Input;
namespace System.Windows.Forms;
internal interface ICommandBindingTargetProvider
{
/// <summary>
/// Occurs when the <see cref="Command"/> property has changed.
/// </summary>
event EventHandler? CommandChanged;
/// <summary>
/// Occurs when the execution context of the <see cref="Command"/> was changed.
/// </summary>
event EventHandler? CommandCanExecuteChanged;
/// <summary>
/// Gets or sets the Command to invoke, when the implementing Component or Control is triggered by the user.
/// </summary>
ICommand? Command { get; set; }
/// <summary>
/// Gets or sets the CommandParameter for the Component or Control.
/// </summary>
object? CommandParameter { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the control can respond to user interaction.
/// </summary>
bool Enabled { get; set; }
/// <summary>
/// Gets or sets the previous value of the <see cref="Enabled"/> property, so that it can be restored to
/// its original value on assignment of a new command.
/// </summary>
protected bool? PreviousEnabledStatus { get; set; }
/// <summary>
/// An implementation should raise the <see cref="CommandChanged"/> event by calling component's or
/// control's OnRaiseCommandChanged method.
/// </summary>
/// <param name="e">An empty <see cref="EventArgs"/> instance.</param>
protected void RaiseCommandChanged(EventArgs e);
/// <summary>
/// An implementation should raise the <see cref="CommandCanExecuteChanged"/> event
/// by calling component's or control's OnCommandCanExecuteChanged method.
/// </summary>
/// <param name="e">An empty <see cref="EventArgs"/> instance.</param>
protected void RaiseCommandCanExecuteChanged(EventArgs e);
/// <summary>
/// Method which should be called by a class implementing this interface in the setter of the
/// <see cref="Command"/> property.
/// </summary>
/// <param name="commandComponent">Instance of the class implementing this interface.</param>
/// <param name="newCommand">The new value of the <see cref="Command"/>
/// which should be assigned to the property.</param>
/// <param name="commandBackingField">
/// The backing field for the <see cref="Command"/> property.
/// </param>
protected static void CommandSetter(
ICommandBindingTargetProvider commandComponent,
ICommand? newCommand,
ref ICommand? commandBackingField)
=> commandComponent.CommandSetter(newCommand, ref commandBackingField);
/// <summary>
/// Method which should be called by the class implementing this interface, when the assigned
/// <see cref="Command"/> should be executed.
/// </summary>
/// <remarks>
/// <para>
/// As an example, a <see cref="Button"/> should call this method inside the method which
/// also raises the <see cref="Control.Click"/> Event of that Button, which
/// would be the <see cref="Button.OnClick(EventArgs)"/> OnClick method.
/// See <see cref="ButtonBase"/> for an example implementation.
/// </para>
/// </remarks>
/// <param name="commandComponent"></param>
protected static void RequestCommandExecute(ICommandBindingTargetProvider commandComponent)
{
commandComponent.Command?.Execute(commandComponent.CommandParameter);
}
private void CommandSetter(
ICommand? newCommand,
ref ICommand? commandBackingField)
{
if (!Equals(commandBackingField, newCommand))
{
if (commandBackingField is not null)
{
commandBackingField.CanExecuteChanged -= CommandCanExecuteChangedProc;
// We need to restore Enabled, should we go from a defined Command to an undefined Command.
if (newCommand is null)
{
if (PreviousEnabledStatus.HasValue)
{
Enabled = PreviousEnabledStatus.Value;
PreviousEnabledStatus = null;
}
}
}
commandBackingField = newCommand;
RaiseCommandChanged(EventArgs.Empty);
if (commandBackingField is null)
{
return;
}
commandBackingField.CanExecuteChanged += CommandCanExecuteChangedProc;
PreviousEnabledStatus ??= Enabled;
Enabled = commandBackingField.CanExecute(CommandParameter);
}
}
private void CommandCanExecuteChangedProc([AllowNull] object sender, EventArgs e)
{
RaiseCommandCanExecuteChanged(e);
Enabled = Command?.CanExecute(CommandParameter) ?? false;
}
}
|