using System; using System.Reflection; using System.Windows.Input; namespace Xamarin.Forms { public sealed class Command : Command { public Command(Action execute) : base(o => { if (IsValidParameter(o)) { execute((T)o); } }) { if (execute == null) { throw new ArgumentNullException(nameof(execute)); } } public Command(Action execute, Func canExecute) : base(o => { if (IsValidParameter(o)) { execute((T)o); } }, o => IsValidParameter(o) && canExecute((T)o)) { if (execute == null) throw new ArgumentNullException(nameof(execute)); if (canExecute == null) throw new ArgumentNullException(nameof(canExecute)); } static bool IsValidParameter(object o) { if (o != null) { // The parameter isn't null, so we don't have to worry whether null is a valid option return o is T; } var t = typeof(T); // The parameter is null. Is T Nullable? if (Nullable.GetUnderlyingType(t) != null) { return true; } // Not a Nullable, if it's a value type then null is not valid return !t.GetTypeInfo().IsValueType; } } public class Command : ICommand { readonly Func _canExecute; readonly Action _execute; public Command(Action execute) { if (execute == null) throw new ArgumentNullException(nameof(execute)); _execute = execute; } public Command(Action execute) : this(o => execute()) { if (execute == null) throw new ArgumentNullException(nameof(execute)); } public Command(Action execute, Func canExecute) : this(execute) { if (canExecute == null) throw new ArgumentNullException(nameof(canExecute)); _canExecute = canExecute; } public Command(Action execute, Func canExecute) : this(o => execute(), o => canExecute()) { if (execute == null) throw new ArgumentNullException(nameof(execute)); if (canExecute == null) throw new ArgumentNullException(nameof(canExecute)); } public bool CanExecute(object parameter) { if (_canExecute != null) return _canExecute(parameter); return true; } public event EventHandler CanExecuteChanged; public void Execute(object parameter) { _execute(parameter); } public void ChangeCanExecute() { EventHandler changed = CanExecuteChanged; changed?.Invoke(this, EventArgs.Empty); } } }