Skip to content

Instantly share code, notes, and snippets.

@mr5z
Created March 2, 2021 13:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mr5z/3cfbaf01011fa84dca03ff4eec21f5dc to your computer and use it in GitHub Desktop.
Save mr5z/3cfbaf01011fa84dca03ff4eec21f5dc to your computer and use it in GitHub Desktop.
Smart and Non-async/Async implementation of ICommand
// You need Prism though :)
public class AdaptiveCommand : DelegateCommand
{
private const double DefaultInvocationDelay = 0.7;
public double InvocationDelayInSeconds { get; set; }
private DateTime lastInvokeTime = DateTime.MinValue;
private readonly Func<bool>? canExecute;
private readonly Func<Task>? task;
public AdaptiveCommand(
Action executeAction,
double invocationDelayInSeconds = DefaultInvocationDelay)
: base(executeAction)
{
InvocationDelayInSeconds = invocationDelayInSeconds;
}
public AdaptiveCommand(
Func<Task> task,
double invocationDelayInSeconds = DefaultInvocationDelay)
: base(() => { })
{
this.task = task;
InvocationDelayInSeconds = invocationDelayInSeconds;
}
public AdaptiveCommand(
Action executeAction,
Func<bool> canExecute,
double invocationDelayInSeconds = DefaultInvocationDelay)
: base(executeAction, canExecute)
{
this.canExecute = canExecute;
InvocationDelayInSeconds = invocationDelayInSeconds;
}
protected override void Execute(object parameter)
{
if (DateTime.Now - lastInvokeTime < TimeSpan.FromSeconds(InvocationDelayInSeconds))
return;
if (IsActive || (canExecute != null && !canExecute()))
return;
IsActive = true;
if (task != null)
{
_ = task().ContinueWith(t => IsActive = false);
}
else
{
base.Execute(parameter);
IsActive = false;
}
lastInvokeTime = DateTime.Now;
}
protected override void OnIsActiveChanged()
{
base.OnIsActiveChanged();
RaiseCanExecuteChanged();
}
protected override bool CanExecute(object parameter)
{
return !IsActive;
}
}
public class AdaptiveCommand<T> : DelegateCommand<T>
{
private const double DefaultInvocationDelay = 0.7;
public double InvocationDelayInSeconds { get; set; }
private DateTime lastInvokeTime = DateTime.MinValue;
private readonly Func<T, bool>? canExecute;
private readonly Func<T, Task>? task;
public AdaptiveCommand(
Action<T> executeAction,
double invocationDelayInSeconds = DefaultInvocationDelay)
: base(executeAction)
{
InvocationDelayInSeconds = invocationDelayInSeconds;
}
public AdaptiveCommand(
Func<T, Task> task,
double invocationDelayInSeconds = DefaultInvocationDelay)
: base(t => { })
{
this.task = task;
InvocationDelayInSeconds = invocationDelayInSeconds;
}
public AdaptiveCommand(
Action<T> executeAction,
Func<T, bool> canExecute,
double invocationDelayInSeconds = DefaultInvocationDelay)
: base(executeAction, canExecute)
{
this.canExecute = canExecute;
InvocationDelayInSeconds = invocationDelayInSeconds;
}
protected override void Execute(object parameter)
{
if (DateTime.Now - lastInvokeTime < TimeSpan.FromSeconds(InvocationDelayInSeconds))
return;
if (IsActive || (canExecute != null && !canExecute((T)parameter)))
return;
IsActive = true;
if (task != null)
{
_ = task((T)parameter).ContinueWith(t => IsActive = false);
}
else
{
base.Execute(parameter);
IsActive = false;
}
lastInvokeTime = DateTime.Now;
}
protected override void OnIsActiveChanged()
{
base.OnIsActiveChanged();
RaiseCanExecuteChanged();
}
protected override bool CanExecute(object parameter)
{
return !IsActive;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment