From 67f9547daf721177c67d5f81e9326f4c2718e1bb Mon Sep 17 00:00:00 2001 From: Ali Yousefi Date: Mon, 13 Nov 2023 09:08:42 +0330 Subject: [PATCH] Add Support for TaskRelayCommand and IBusyViewModel --- .../BaseViewModel.cs | 11 +- .../Commands/BaseCommand.cs | 63 ++++++++++- .../Commands/TaskBaseCommand.cs | 106 ++++++++++++++++++ .../Commands/TaskRelayCommand.cs | 106 ++++++++++++++++++ .../EasyMicroservices.UI.Core.Mvvm.csproj | 2 +- .../Interfaces/IBusyViewModel.cs | 38 +++++++ 6 files changed, 317 insertions(+), 9 deletions(-) create mode 100644 src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/TaskBaseCommand.cs create mode 100644 src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/TaskRelayCommand.cs create mode 100644 src/CSharp/EasyMicroservices.UI.Core.Mvvm/Interfaces/IBusyViewModel.cs diff --git a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/BaseViewModel.cs b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/BaseViewModel.cs index 76fe373..412d7b2 100644 --- a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/BaseViewModel.cs +++ b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/BaseViewModel.cs @@ -1,4 +1,5 @@ using EasyMicroservices.ServiceContracts; +using EasyMicroservices.UI.Core.Interfaces; using System; using System.ComponentModel; using System.Threading.Tasks; @@ -8,8 +9,13 @@ namespace EasyMicroservices.UI.Core; /// /// /// -public abstract class BaseViewModel : INotifyPropertyChanged +public abstract class BaseViewModel : IBusyViewModel, INotifyPropertyChanged { + /// + /// + /// + public Action OnBusyChanged { get; set; } + bool _IsBusy; /// /// @@ -20,6 +26,7 @@ public virtual bool IsBusy set { _IsBusy = value; + OnBusyChanged?.Invoke(value); OnPropertyChanged(nameof(IsBusy)); } } @@ -128,7 +135,7 @@ public virtual async Task ExecuteApi(Func> getServerResult, Func /// /// - public virtual Task DisplayError(Exception exception) + public virtual Task OnError(Exception exception) { return Task.CompletedTask; } diff --git a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/BaseCommand.cs b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/BaseCommand.cs index cd8c9e7..a27c467 100644 --- a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/BaseCommand.cs +++ b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/BaseCommand.cs @@ -1,4 +1,5 @@ -using System; +using EasyMicroservices.UI.Core.Interfaces; +using System; using System.Windows.Input; namespace EasyMicroservices.UI.Core.Commands; @@ -12,8 +13,18 @@ public abstract class BaseCommand : ICommand /// /// public event EventHandler CanExecuteChanged; - private readonly Action _execute = null; - private readonly Func _canExecute = null; + /// + /// + /// + protected readonly Action _execute = null; + /// + /// + /// + protected readonly Func _canExecute = null; + /// + /// / + /// + protected readonly IBusyViewModel _busyViewModel = null; /// /// @@ -26,6 +37,19 @@ public BaseCommand(Action execute, Func canExecute) _canExecute = canExecute; } + /// + /// + /// + /// + /// + /// + public BaseCommand(IBusyViewModel busyViewModel, Action execute, Func canExecute) + { + _execute = execute; + _canExecute = canExecute; + _busyViewModel = busyViewModel; + } + /// /// /// @@ -33,8 +57,15 @@ public BaseCommand(Action execute, Func canExecute) /// public virtual bool CanExecute(object parameter = null) { - CanExecuteChanged?.Invoke(this, new EventArgs()); - return _canExecute == null || _canExecute(parameter); + try + { + return _canExecute == null || _canExecute(parameter); + } + catch (Exception ex) + { + _busyViewModel?.OnError(ex); + throw; + } } /// @@ -43,6 +74,26 @@ public virtual bool CanExecute(object parameter = null) /// public virtual void Execute(object parameter) { - _execute(parameter); + try + { + if (_busyViewModel != null) + { + _busyViewModel.Busy(); + CanExecuteChanged?.Invoke(this, new EventArgs()); + } + _execute(parameter); + } + catch (Exception ex) + { + _busyViewModel?.OnError(ex); + } + finally + { + if (_busyViewModel != null) + { + _busyViewModel.UnBusy(); + CanExecuteChanged?.Invoke(this, new EventArgs()); + } + } } } diff --git a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/TaskBaseCommand.cs b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/TaskBaseCommand.cs new file mode 100644 index 0000000..9da5e67 --- /dev/null +++ b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/TaskBaseCommand.cs @@ -0,0 +1,106 @@ +using EasyMicroservices.UI.Core.Interfaces; +using System; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace EasyMicroservices.UI.Core.Commands +{ + /// + /// + /// + public class TaskBaseCommand : ICommand + { + /// + /// + /// + public event EventHandler CanExecuteChanged; + /// + /// + /// + protected readonly Func _execute = null; + /// + /// + /// + protected readonly Func _canExecute = null; + /// + /// / + /// + protected readonly IBusyViewModel _busyViewModel = null; + + /// + /// + /// + /// + /// + public TaskBaseCommand(Func execute, Func canExecute) + { + _execute = execute; + _canExecute = canExecute; + } + + /// + /// + /// + /// + /// + /// + public TaskBaseCommand(IBusyViewModel busyViewModel, Func execute, Func canExecute) + { + _execute = execute; + _canExecute = canExecute; + _busyViewModel = busyViewModel; + } + + /// + /// + /// + /// + /// + public virtual bool CanExecute(object parameter = null) + { + try + { + return _canExecute == null || _canExecute(parameter); + } + catch (Exception ex) + { + _busyViewModel?.OnError(ex); + throw; + } + } + + /// + /// + /// + /// + public virtual void Execute(object parameter) + { + if (_busyViewModel != null) + { + _busyViewModel.Busy(); + CanExecuteChanged?.Invoke(this, new EventArgs()); + } + _ = InternalExecute(parameter); + } + + async Task InternalExecute(object parameter) + { + try + { + await _execute(parameter); + } + catch (Exception ex) + { + _busyViewModel?.OnError(ex); + } + finally + { + if (_busyViewModel != null) + { + _busyViewModel.UnBusy(); + CanExecuteChanged?.Invoke(this, new EventArgs()); + } + } + } + } +} \ No newline at end of file diff --git a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/TaskRelayCommand.cs b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/TaskRelayCommand.cs new file mode 100644 index 0000000..4f86cbb --- /dev/null +++ b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Commands/TaskRelayCommand.cs @@ -0,0 +1,106 @@ +using EasyMicroservices.UI.Core.Interfaces; +using System; +using System.Threading.Tasks; + +namespace EasyMicroservices.UI.Core.Commands +{ + /// + /// + /// + public class TaskRelayCommand : TaskBaseCommand + { + /// + /// + /// + /// + /// + public TaskRelayCommand(Func execute, Func canExecute) + : this(default, execute, canExecute) + { + + } + + /// + /// + /// + /// + public TaskRelayCommand(Func execute) + : this(default, execute, () => true) + { + + } + + /// + /// + /// + /// + /// + /// + public TaskRelayCommand(IBusyViewModel busyViewModel, Func execute, Func canExecute) + : base(busyViewModel, (x) => execute(), (x) => canExecute()) + { + + } + + /// + /// + /// + /// + /// + public TaskRelayCommand(IBusyViewModel busyViewModel, Func execute) + : this(busyViewModel, execute, () => true) + { + + } + } + + /// + /// + /// + public class TaskRelayCommand : TaskBaseCommand + { + /// + /// + /// + /// + /// + public TaskRelayCommand(Func execute, Func canExecute) + : this(default, execute, canExecute) + { + + } + + /// + /// + /// + /// + public TaskRelayCommand(Func execute) + : this(default, execute, (x) => true) + { + + } + + /// + /// + /// + /// + /// + /// + public TaskRelayCommand(IBusyViewModel busyViewModel, Func execute, Func canExecute) + : base(busyViewModel, (x) => execute((T)x), (x) => canExecute((T)x)) + { + + } + + /// + /// + /// + /// + /// + public TaskRelayCommand(IBusyViewModel busyViewModel, Func execute) + : this(busyViewModel, execute, (x) => true) + { + + } + } +} diff --git a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/EasyMicroservices.UI.Core.Mvvm.csproj b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/EasyMicroservices.UI.Core.Mvvm.csproj index 960a983..28a4e5b 100644 --- a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/EasyMicroservices.UI.Core.Mvvm.csproj +++ b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/EasyMicroservices.UI.Core.Mvvm.csproj @@ -5,7 +5,7 @@ AnyCPU;x64;x86 EasyMicroservices true - 0.0.0.3 + 0.0.0.4 Model View View Model EasyMicroservices@gmail.com mvvm,mvpvm,modelview,modelviewviewmodel diff --git a/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Interfaces/IBusyViewModel.cs b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Interfaces/IBusyViewModel.cs new file mode 100644 index 0000000..b3cab0f --- /dev/null +++ b/src/CSharp/EasyMicroservices.UI.Core.Mvvm/Interfaces/IBusyViewModel.cs @@ -0,0 +1,38 @@ +using System; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace EasyMicroservices.UI.Core.Interfaces +{ + /// + /// + /// + public interface IBusyViewModel : INotifyPropertyChanged + { + /// + /// + /// + Action OnBusyChanged { get; set; } + + /// + /// + /// + bool IsBusy { get; set; } + + /// + /// + /// + void Busy(); + + /// + /// + /// + void UnBusy(); + /// + /// + /// + /// + /// + Task OnError(Exception exception); + } +}