2021-07-23 09:42:22 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Windows.Input;
|
|
|
|
|
|
|
2023-01-25 15:58:05 +08:00
|
|
|
|
namespace AIStudio.Wpf.DiagramDesigner.Additionals.Commands
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// This class allows delegating the commanding logic to methods passed as parameters,
|
|
|
|
|
|
/// and enables a View to bind commands to objects that are not part of the element tree.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class CanExecuteDelegateCommand : IDelegateCommand
|
|
|
|
|
|
{
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action executeMethod)
|
|
|
|
|
|
: this(executeMethod, null, false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
|
|
|
|
|
|
: this(executeMethod, canExecuteMethod, false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action executeMethod, Func<bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (executeMethod == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new ArgumentNullException("executeMethod");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_executeMethod = executeMethod;
|
|
|
|
|
|
_canExecuteMethod = canExecuteMethod;
|
|
|
|
|
|
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Method to determine if the command can be executed
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool CanExecute()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_canExecuteMethod != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _canExecuteMethod();
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Execution of the command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void Execute()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_executeMethod != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_executeMethod();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public object Target
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_executeMethod == null)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
return _executeMethod.Target;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Property to enable or disable CommandManager's automatic requery on this command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool IsAutomaticRequeryDisabled
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return _isAutomaticRequeryDisabled;
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_isAutomaticRequeryDisabled != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
_isAutomaticRequeryDisabled = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Raises the CanExecuteChaged event
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void RaiseCanExecuteChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
OnCanExecuteChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Protected virtual method to raise CanExecuteChanged event
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnCanExecuteChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region ICommand Members
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// ICommand.CanExecuteChanged implementation
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public event EventHandler CanExecuteChanged
|
|
|
|
|
|
{
|
|
|
|
|
|
add
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested += value;
|
|
|
|
|
|
}
|
|
|
|
|
|
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
remove
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested -= value;
|
|
|
|
|
|
}
|
|
|
|
|
|
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ICommand.CanExecute(object parameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
return CanExecute();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ICommand.Execute(object parameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
Execute();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Data
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Action _executeMethod = null;
|
|
|
|
|
|
private readonly Func<bool> _canExecuteMethod = null;
|
|
|
|
|
|
private bool _isAutomaticRequeryDisabled = false;
|
|
|
|
|
|
private List<WeakReference> _canExecuteChangedHandlers;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class CanExecuteDelegateCommand<T1> : IDelegateCommand
|
|
|
|
|
|
{
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1> executeMethod)
|
|
|
|
|
|
: this(executeMethod, null, false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1> executeMethod, Func<T1, bool> canExecuteMethod)
|
|
|
|
|
|
: this(executeMethod, canExecuteMethod, false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1> executeMethod, Func<T1, bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (executeMethod == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new ArgumentNullException("executeMethod");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_executeMethod = executeMethod;
|
|
|
|
|
|
_canExecuteMethod = canExecuteMethod;
|
|
|
|
|
|
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Method to determine if the command can be executed
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool CanExecute(T1 parameter1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_canExecuteMethod != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _canExecuteMethod(parameter1);
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Execution of the command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void Execute(T1 parameter1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_executeMethod != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_executeMethod(parameter1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Raises the CanExecuteChaged event
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void RaiseCanExecuteChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
OnCanExecuteChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Protected virtual method to raise CanExecuteChanged event
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnCanExecuteChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Property to enable or disable CommandManager's automatic requery on this command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool IsAutomaticRequeryDisabled
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return _isAutomaticRequeryDisabled;
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_isAutomaticRequeryDisabled != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
_isAutomaticRequeryDisabled = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public object Target
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_executeMethod == null)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
return _executeMethod.Target;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region ICommand Members
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// ICommand.CanExecuteChanged implementation
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public event EventHandler CanExecuteChanged
|
|
|
|
|
|
{
|
|
|
|
|
|
add
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested += value;
|
|
|
|
|
|
}
|
|
|
|
|
|
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
remove
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested -= value;
|
|
|
|
|
|
}
|
|
|
|
|
|
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual bool CanExecute(object parameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (parameter == null || (parameter is object[] && (parameter as object[]).Length < 1))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
if (parameter is object[])
|
|
|
|
|
|
{
|
|
|
|
|
|
object[] parameters = parameter as object[];
|
|
|
|
|
|
|
|
|
|
|
|
// if T is of value type and the parameter is not
|
|
|
|
|
|
// set yet, then return false if CanExecute delegate
|
|
|
|
|
|
// exists, else return true
|
|
|
|
|
|
if ((parameters[0] != null && !typeof(T1).IsAssignableFrom(parameters[0].GetType()))
|
|
|
|
|
|
|| (parameters[0] == null && typeof(T1).IsValueType)
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return CanExecute((T1)parameters[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (parameter != null && !typeof(T1).IsAssignableFrom(parameter.GetType()))
|
|
|
|
|
|
parameter = null;
|
|
|
|
|
|
|
|
|
|
|
|
return CanExecute((T1)parameter);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual void Execute(object parameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
//如果T1不允许为空,而parameter参数又为空,则直接返回
|
|
|
|
|
|
if (typeof(T1).IsValueType && (parameter == null || (parameter is object[] && (parameter as object[]).Length < 1)))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (parameter is object[])
|
|
|
|
|
|
{
|
|
|
|
|
|
object[] parameters = parameter as object[];
|
|
|
|
|
|
|
|
|
|
|
|
// if T1 is of value type and the parameter is not
|
|
|
|
|
|
// set yet, then return false if CanExecute delegate
|
|
|
|
|
|
// exists, else return true
|
|
|
|
|
|
if ((parameters[0] != null && !typeof(T1).IsAssignableFrom(parameters[0].GetType()))
|
|
|
|
|
|
|| (parameters[0] == null && typeof(T1).IsValueType)
|
|
|
|
|
|
)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
Execute((T1)parameters[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (parameter != null && !typeof(T1).IsAssignableFrom(parameter.GetType()))
|
|
|
|
|
|
parameter = null;
|
|
|
|
|
|
|
|
|
|
|
|
Execute((T1)parameter);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Data
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Action<T1> _executeMethod = null;
|
|
|
|
|
|
private readonly Func<T1, bool> _canExecuteMethod = null;
|
|
|
|
|
|
private bool _isAutomaticRequeryDisabled = false;
|
|
|
|
|
|
private List<WeakReference> _canExecuteChangedHandlers;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class CanExecuteDelegateCommand<T1, T2> : IDelegateCommand
|
|
|
|
|
|
{
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1, T2> executeMethod)
|
|
|
|
|
|
: this(executeMethod, null, false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1, T2> executeMethod, Func<T1, T2, bool> canExecuteMethod)
|
|
|
|
|
|
: this(executeMethod, canExecuteMethod, false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1, T2> executeMethod, Func<T1, T2, bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (executeMethod == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new ArgumentNullException("executeMethod");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_executeMethod = executeMethod;
|
|
|
|
|
|
_canExecuteMethod = canExecuteMethod;
|
|
|
|
|
|
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Method to determine if the command can be executed
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool CanExecute(T1 parameter1, T2 parameter2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_canExecuteMethod != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _canExecuteMethod(parameter1, parameter2);
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Execution of the command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void Execute(T1 parameter1, T2 parameter2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_executeMethod != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_executeMethod(parameter1, parameter2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Raises the CanExecuteChaged event
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void RaiseCanExecuteChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
OnCanExecuteChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Protected virtual method to raise CanExecuteChanged event
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnCanExecuteChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Property to enable or disable CommandManager's automatic requery on this command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool IsAutomaticRequeryDisabled
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return _isAutomaticRequeryDisabled;
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_isAutomaticRequeryDisabled != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
_isAutomaticRequeryDisabled = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public object Target
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_executeMethod == null)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
return _executeMethod.Target;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region ICommand Members
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// ICommand.CanExecuteChanged implementation
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public event EventHandler CanExecuteChanged
|
|
|
|
|
|
{
|
|
|
|
|
|
add
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested += value;
|
|
|
|
|
|
}
|
|
|
|
|
|
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
remove
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested -= value;
|
|
|
|
|
|
}
|
|
|
|
|
|
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual bool CanExecute(object parameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (parameter == null || !(parameter is object[]) || (parameter as object[]).Length < 2)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
object[] parameters = parameter as object[];
|
|
|
|
|
|
|
|
|
|
|
|
// if T is of value type and the parameter is not
|
|
|
|
|
|
// set yet, then return false if CanExecute delegate
|
|
|
|
|
|
// exists, else return true
|
|
|
|
|
|
if ((parameters[0] != null && !typeof(T1).IsAssignableFrom(parameters[0].GetType()))
|
|
|
|
|
|
|| (parameters[0] == null && typeof(T1).IsValueType)
|
|
|
|
|
|
|| (parameters[1] != null && !typeof(T2).IsAssignableFrom(parameters[1].GetType()))
|
|
|
|
|
|
|| (parameters[1] == null && typeof(T2).IsValueType)
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return CanExecute((T1)parameters[0], (T2)parameters[1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual void Execute(object parameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (parameter == null || !(parameter is object[]) || (parameter as object[]).Length < 2)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
object[] parameters = parameter as object[];
|
|
|
|
|
|
|
|
|
|
|
|
// if T is of value type and the parameter is not
|
|
|
|
|
|
// set yet, then return false if CanExecute delegate
|
|
|
|
|
|
// exists, else return true
|
|
|
|
|
|
if ((parameters[0] != null && !typeof(T1).IsAssignableFrom(parameters[0].GetType()))
|
|
|
|
|
|
|| (parameters[0] == null && typeof(T1).IsValueType)
|
|
|
|
|
|
|| (parameters[1] != null && !typeof(T2).IsAssignableFrom(parameters[1].GetType()))
|
|
|
|
|
|
|| (parameters[1] == null && typeof(T2).IsValueType)
|
|
|
|
|
|
)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
Execute((T1)parameters[0], (T2)parameters[1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Data
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Action<T1, T2> _executeMethod = null;
|
|
|
|
|
|
private readonly Func<T1, T2, bool> _canExecuteMethod = null;
|
|
|
|
|
|
private bool _isAutomaticRequeryDisabled = false;
|
|
|
|
|
|
private List<WeakReference> _canExecuteChangedHandlers;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class CanExecuteDelegateCommand<T1, T2, T3> : IDelegateCommand
|
|
|
|
|
|
{
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1, T2, T3> executeMethod)
|
|
|
|
|
|
: this(executeMethod, null, false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1, T2, T3> executeMethod, Func<T1, T2, T3, bool> canExecuteMethod)
|
|
|
|
|
|
: this(executeMethod, canExecuteMethod, false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public CanExecuteDelegateCommand(Action<T1, T2, T3> executeMethod, Func<T1, T2, T3, bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (executeMethod == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new ArgumentNullException("executeMethod");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_executeMethod = executeMethod;
|
|
|
|
|
|
_canExecuteMethod = canExecuteMethod;
|
|
|
|
|
|
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Method to determine if the command can be executed
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool CanExecute(T1 parameter1, T2 parameter2, T3 parameter3)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_canExecuteMethod != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _canExecuteMethod(parameter1, parameter2, parameter3);
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Execution of the command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void Execute(T1 parameter1, T2 parameter2, T3 parameter3)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_executeMethod != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_executeMethod(parameter1, parameter2, parameter3);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Raises the CanExecuteChaged event
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void RaiseCanExecuteChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
OnCanExecuteChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Protected virtual method to raise CanExecuteChanged event
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected virtual void OnCanExecuteChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Property to enable or disable CommandManager's automatic requery on this command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool IsAutomaticRequeryDisabled
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return _isAutomaticRequeryDisabled;
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_isAutomaticRequeryDisabled != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
|
|
|
|
|
|
}
|
|
|
|
|
|
_isAutomaticRequeryDisabled = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public object Target
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_executeMethod == null)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
return _executeMethod.Target;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region ICommand Members
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// ICommand.CanExecuteChanged implementation
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public event EventHandler CanExecuteChanged
|
|
|
|
|
|
{
|
|
|
|
|
|
add
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested += value;
|
|
|
|
|
|
}
|
|
|
|
|
|
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
remove
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isAutomaticRequeryDisabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested -= value;
|
|
|
|
|
|
}
|
|
|
|
|
|
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual bool CanExecute(object parameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (parameter == null || !(parameter is object[]) || (parameter as object[]).Length < 3)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
object[] parameters = parameter as object[];
|
|
|
|
|
|
|
|
|
|
|
|
// if T is of value type and the parameter is not
|
|
|
|
|
|
// set yet, then return false if CanExecute delegate
|
|
|
|
|
|
// exists, else return true
|
|
|
|
|
|
if ((parameters[0] != null && !typeof(T1).IsAssignableFrom(parameters[0].GetType()))
|
|
|
|
|
|
|| (parameters[0] == null && typeof(T1).IsValueType)
|
|
|
|
|
|
|| (parameters[1] != null && !typeof(T2).IsAssignableFrom(parameters[1].GetType()))
|
|
|
|
|
|
|| (parameters[1] == null && typeof(T2).IsValueType)
|
|
|
|
|
|
|| (parameters[2] != null && !typeof(T3).IsAssignableFrom(parameters[2].GetType()))
|
|
|
|
|
|
|| (parameters[2] == null && typeof(T3).IsValueType)
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return CanExecute((T1)parameters[0], (T2)parameters[1], (T3)parameters[2]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual void Execute(object parameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (parameter == null || !(parameter is object[]) || (parameter as object[]).Length < 3)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
object[] parameters = parameter as object[];
|
|
|
|
|
|
|
|
|
|
|
|
// if T is of value type and the parameter is not
|
|
|
|
|
|
// set yet, then return false if CanExecute delegate
|
|
|
|
|
|
// exists, else return true
|
|
|
|
|
|
if ((parameters[0] != null && !typeof(T1).IsAssignableFrom(parameters[0].GetType()))
|
|
|
|
|
|
|| (parameters[0] == null && typeof(T1).IsValueType)
|
|
|
|
|
|
|| (parameters[1] != null && !typeof(T2).IsAssignableFrom(parameters[1].GetType()))
|
|
|
|
|
|
|| (parameters[1] == null && typeof(T2).IsValueType)
|
|
|
|
|
|
|| (parameters[2] != null && !typeof(T3).IsAssignableFrom(parameters[2].GetType()))
|
|
|
|
|
|
|| (parameters[2] == null && typeof(T3).IsValueType)
|
|
|
|
|
|
)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
Execute((T1)parameters[0], (T2)parameters[1], (T3)parameters[2]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Data
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Action<T1, T2, T3> _executeMethod = null;
|
|
|
|
|
|
private readonly Func<T1, T2, T3, bool> _canExecuteMethod = null;
|
|
|
|
|
|
private bool _isAutomaticRequeryDisabled = false;
|
|
|
|
|
|
private List<WeakReference> _canExecuteChangedHandlers;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public interface IDelegateCommand : ICommand
|
|
|
|
|
|
{
|
|
|
|
|
|
object Target { get; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// This class contains methods for the CommandManager that help avoid memory leaks by
|
|
|
|
|
|
/// using weak references.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
internal class CommandManagerHelper
|
|
|
|
|
|
{
|
|
|
|
|
|
internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (handlers != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Take a snapshot of the handlers before we call out to them since the handlers
|
|
|
|
|
|
// could cause the array to me modified while we are reading it.
|
|
|
|
|
|
|
|
|
|
|
|
EventHandler[] callees = new EventHandler[handlers.Count];
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = handlers.Count - 1; i >= 0; i--)
|
|
|
|
|
|
{
|
|
|
|
|
|
WeakReference reference = handlers[i];
|
|
|
|
|
|
EventHandler handler = reference.Target as EventHandler;
|
|
|
|
|
|
if (handler == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Clean up old handlers that have been collected
|
|
|
|
|
|
handlers.RemoveAt(i);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
callees[count] = handler;
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Call the handlers that we snapshotted
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
EventHandler handler = callees[i];
|
|
|
|
|
|
handler(null, EventArgs.Empty);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (handlers != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (WeakReference handlerRef in handlers)
|
|
|
|
|
|
{
|
|
|
|
|
|
EventHandler handler = handlerRef.Target as EventHandler;
|
|
|
|
|
|
if (handler != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested += handler;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (handlers != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (WeakReference handlerRef in handlers)
|
|
|
|
|
|
{
|
|
|
|
|
|
EventHandler handler = handlerRef.Target as EventHandler;
|
|
|
|
|
|
if (handler != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommandManager.RequerySuggested -= handler;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler)
|
|
|
|
|
|
{
|
|
|
|
|
|
AddWeakReferenceHandler(ref handlers, handler, -1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (handlers == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
handlers.Add(new WeakReference(handler));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (handlers != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = handlers.Count - 1; i >= 0; i--)
|
|
|
|
|
|
{
|
|
|
|
|
|
WeakReference reference = handlers[i];
|
|
|
|
|
|
EventHandler existingHandler = reference.Target as EventHandler;
|
|
|
|
|
|
if ((existingHandler == null) || (existingHandler == handler))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Clean up old handlers that have been collected
|
|
|
|
|
|
// in addition to the handler that is to be removed.
|
|
|
|
|
|
handlers.RemoveAt(i);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|