I'm trying to bridge the gap between the ICommand world and the async word. Most ICommand implementations are synchronous in nature which makes it messy to bridge the gap to asynchronous interfaces like...oh say INaviagation in the view model. I took a look for a AsyncCommand in Xamarin but didn't find it, now I suspect I know why. I thought that I could just use the standard event mechanisms but a few other posts on this forum seem to indicate that the same issue with async/await exists there as well.
P.S. A simple test using standard wpf with the RelayAsyncCommand works just fine.
P.P.S Mitch, before you ask my version is : 1.2.3.6257
I have a simple modal that I need to dismiss when a back button is pressed.
`
class ModViewModel : BaseViewModel
{
private readonly AdminMessageModel _msg;
private readonly INavigation _navigation;
public ModViewModel(AdminMessageModel msg,INavigation navigation)
{
_msg = msg;
_navigation = navigation;
Dismiss=new RelayAsyncCommand(async (o) =>
{
await _navigation.PopModalAsync();
});
Reply=new RelayCommand((o)=>{});
}
public AdminMessageModel Message { get { return _msg; } }
public RelayAsyncCommand<AdminMessageModel> Dismiss { get; set; }
public RelayCommand Reply { get; set; }
}
RelayAsyncCommand is implemented as follows
class RelayAsyncCommand : ICommand where T: class
{
private readonly Func<T,Task> _asyncExecute;
private readonly Predicate _canexecute;
public event EventHandler CanExecuteChanged;
private readonly ManualResetEvent _waiter=new ManualResetEvent(false);
//Utitily method
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
public RelayAsyncCommand(Func<T,Task> asyncAsyncExecute,Predicate<T> predicate=null)
{
_asyncExecute = asyncAsyncExecute;
_canexecute = predicate;
}
//CanExecute is currently assumed to be sync
public bool CanExecute(object annoyingbaseobjectthing)
{
return (_canexecute == null || _canexecute(annoyingbaseobjectthing as T));
}
public async void Execute(object annoyingbaseobjectthing)
{
if (_asyncExecute != null)
{
await ExecuteAync(annoyingbaseobjectthing as T);
}
}
protected virtual async Task ExecuteAync(T param)
{
try
{
//Code goes BOOOOOM here
await _asyncExecute(param);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
throw;
}
}
}
`