| MAUI-CommunityToolkit-2 :👈 | 👉:MAUI-CommunityToolkit-4 |
๐ Hour 3 โ Commands: RelayCommand & AsyncRelayCommand |
๐ Hour 3 โ Commands: RelayCommand & AsyncRelayCommand
๐๏ธ 1. What Are Commands?
Commands are an MVVM-friendly way to handle user interactions without writing code-behind. A Command is an object that implements ICommand and allows executing logic from UI elements like:
- ๐ Buttons
- ๐ Menu items
- โก๏ธ Gesture recognizers
Why use commands instead of Click events?
- ๐ฆ Keeps UI and logic separate
- ๐ Allows UI to update when command states change
- ๐งช Easier to test
- ๐ Supports MVVM pattern properly
โก 2. RelayCommand โ The Basic Command
RelayCommand is a simple command used for synchronous actions.
Basic Example:
public partial class CounterViewModel : ObservableObject
{
[ObservableProperty]
private int count;
public RelayCommand IncreaseCommand { get; }
public CounterViewModel()
{
IncreaseCommand = new RelayCommand(() =>
{
Count++;
});
}
}
โ Bind this in XAML:
<Button Text="Increase" Command="{Binding IncreaseCommand}" />
๐ก Every click increments the count using MVVM-friendly logic.
๐จ 3. RelayCommand with Parameters
Example:
public RelayCommand<int> AddCommand { get; }
public CounterViewModel()
{
AddCommand = new RelayCommand<int>((value) =>
{
Count += value;
});
}
XAML binding:
<Button Text="+5" Command="{Binding AddCommand}" CommandParameter="5" />
๐ Now you can pass custom values from UI.
โณ 4. AsyncRelayCommand โ For Async Methods
Use AsyncRelayCommand when your logic is asynchronous, such as:
- ๐ API calls
- โณ Long operations
- ๐พ Database access
Example:
public partial class DataViewModel : ObservableObject
{
[ObservableProperty]
private string message;
public IAsyncRelayCommand LoadCommand { get; }
public DataViewModel()
{
LoadCommand = new AsyncRelayCommand(LoadDataAsync);
}
private async Task LoadDataAsync()
{
Message = "Loading...";
await Task.Delay(2000);
Message = "Data Loaded Successfully!";
}
}
XAML:
<Button Text="Load" Command="{Binding LoadCommand}" />
๐ก AsyncRelayCommand automatically disables itself while running.
๐ฆ 5. CanExecute Logic (Enable/Disable Button)
Commands can control whether buttons are enabled using CanExecute.
Example:
public RelayCommand SubmitCommand { get; }
public LoginViewModel()
{
SubmitCommand = new RelayCommand(
Submit,
() => !string.IsNullOrEmpty(Username)
);
}
XAML:
<Button Text="Submit" Command="{Binding SubmitCommand}" />
๐ก The button becomes disabled when Username is empty.
๐งฒ 6. Using [ICommand] Attribute (Advanced Auto-Generation)
MVVM Toolkit can create commands automatically with the [ICommand] attribute.
Example:
public partial class NumberViewModel : ObservableObject
{
[ObservableProperty]
private int total;
[ICommand]
private void Add(int value)
{
Total += value;
}
}
โ This automatically generates an AddCommand.
XAML:
<Button Text="Add 10" Command="{Binding AddCommand}" CommandParameter="10" />
๐ ๏ธ 7. Hands-On Practice for Hour 3
- ๐ Create a simple IncreaseCommand
- โ Add parameter support using RelayCommand<T>
- โณ Create an AsyncRelayCommand that loads fake data
- ๐ฆ Implement CanExecute logic to disable a button
- โก Use [ICommand] attribute to generate a command
- ๐ฑ Bind commands to MAUI/WPF UI buttons
๐ 8. Hour 3 Practice ViewModel (Recommended)
public partial class DemoViewModel : ObservableObject
{
[ObservableProperty]
private int counter;
[ObservableProperty]
private bool isBusy;
public RelayCommand IncreaseCommand { get; }
public RelayCommand<int> AddAmountCommand { get; }
public IAsyncRelayCommand LoadCommand { get; }
public DemoViewModel()
{
IncreaseCommand = new RelayCommand(() => Counter++);
AddAmountCommand = new RelayCommand<int>((value) => Counter += value);
LoadCommand = new AsyncRelayCommand(LoadAsync);
}
private async Task LoadAsync()
{
IsBusy = true;
await Task.Delay(2000);
Counter += 10;
IsBusy = false;
}
}
๐ Covers all command types!
๐ Hour 3 Goals Completed
- โก Understand RelayCommand & AsyncRelayCommand
- ๐จ Use commands with parameters
- โณ Build async commands for loading operations
- ๐ฆ Use CanExecute for button-enable logic
- ๐ช Generate commands automatically with [ICommand]
๐ Hour 3 โ Commands Quiz (RelayCommand & AsyncRelayCommand)
๐ Section A โ Multiple Choice Questions
-
Which class implements ICommand for synchronous operations?
a) AsyncRelayCommand
b) DelegateCommand
c) RelayCommand
d) CommandGenerator -
What does AsyncRelayCommand do automatically?
a) Refresh the UI
b) Disables itself while running
c) Logs exceptions automatically
d) Cancels all other commands -
Which interface does every MVVM command implement?
a) IRunnable
b) IAction
c) ICommand
d) ITrigger -
What is the purpose of the CanExecute method?
a) Runs the command asynchronously
b) Validates parameters
c) Controls whether a command is allowed to execute
d) Logs debug information -
What does the [ICommand] attribute generate automatically?
a) Only a method
b) Only a property
c) A full ICommand (method + generated Command property)
d) XAML markup
๐ง Section B โ True or False
- True / False: RelayCommand can accept parameters.
- True / False: AsyncRelayCommand is useful for API calls.
- True / False: A command without CanExecute is always enabled.
- True / False: The [ICommand] attribute removes the need to write any command manually.
- True / False: Commands should be placed inside ViewModels, not Views.
โ๏ธ Section C โ Short Answer Questions
- Explain the difference between RelayCommand and AsyncRelayCommand.
- Give an example scenario where CanExecute should return false.
- Write a one-line purpose of the ICommand interface.
- Why is command binding preferred over button click events in MVVM?
- What property does [ICommand] automatically generate for a method named Save()?
๐ป Section D โ Code Output / Interpretation
Consider this ViewModel:
public partial class DemoViewModel : ObservableObject
{
[ObservableProperty]
private int score = 0;
[ICommand]
private void AddPoints(int value)
{
Score += value;
}
}
- What is the auto-generated command name?
- What happens in the UI if CommandParameter="5" is used?
- Is this command synchronous or asynchronous?
- Does Score raise PropertyChanged?
๐ฆ Section E โ CanExecute Logic
Given:
public RelayCommand SaveCommand { get; }
public ExampleViewModel()
{
SaveCommand = new RelayCommand(
Save,
() => IsFormValid
);
}
- When will the button be disabled?
- Which method must be called to re-evaluate CanExecute?
- What happens if IsFormValid changes but CanExecuteChanged isn't raised?
๐ Hour 3 โ Commands Quiz Answer Key
โ Section A โ Multiple Choice Answers
- c) RelayCommand
- b) Disables itself while running
- c) ICommand
- c) Controls whether a command is allowed to execute
- c) A full ICommand (method + generated Command property)
๐ง Section B โ True or False Answers
- True โ ObservableObject implements INotifyPropertyChanged.
- True โ Partial methods are optional but useful.
- False โ [NotifyPropertyChangedFor] is applied to fields.
- True โ It generates field + property with notifications.
- False โ Dependent properties update automatically with the attribute.
โ๏ธ Section C โ Short Answer Solutions
-
[ObservableProperty] generates a property with automatic
PropertyChanged notifications.
Example:
[ObservableProperty] private string title; -
[NotifyPropertyChangedFor] ensures dependent properties update
when another changes.
Example: FullName updates when FirstName or LastName changes. -
Partial method example:
partial void OnScoreChanged(int value) { Console.WriteLine("Score changed!"); } - SetProperty() updates the backing field and raises PropertyChanged automatically.
-
OnXChanging runs before value changes.
OnXChanged runs after value changes.
Useful for validation, logging, or updating dependent logic.
๐ป Section D โ Code Output / Interpretation Answers
- AddPointsCommand is generated.
- Score increases by 5 when CommandParameter="5".
- It is a synchronous command (RelayCommand via [ICommand]).
- Yes, Score raises PropertyChanged automatically.
๐ฆ Section E โ CanExecute Logic Answers
- The button is disabled when IsFormValid == false.
- You must call SaveCommand.NotifyCanExecuteChanged().
- The button will not update its enabled/disabled state, even if IsFormValid changes.
๐ End of Hour 3 Answer Key
| MAUI-CommunityToolkit-2 :👈 | 👉:MAUI-CommunityToolkit-4 |