I am using a command binding for a button in Maui. The button's IsEnabled property does not work because of the command binding. Even if IsEnable is set to true, the command is not fired. How can I disable the button in the ViewModel class at the constructor in new Command(..) so that the command does not fire and the button looks disabled? (Like toggling from one to the other button.)
On learn.microsoft.. I read:
Warning
Do not use the IsEnabled property of Button if you're using the command interface.
XAML:
<ScrollView Style="{StaticResource mainScrollView}">
<VerticalStackLayout>
<HorizontalStackLayout>
<Button Text="Month"
Command="{Binding SetMonatCommand}"
Style="{StaticResource buttonCalendar}"
IsEnabled="{Binding IsListActive}"/> <!-- IsEnabled IS NOT WORKING -->
<Button Text="List"
Command="{Binding SetListeCommand}"
Style="{StaticResource buttonCalendar}"
IsEnabled="{Binding IsMonthActive}"/> <!-- IsEnabled IS NOT WORKING -->
</HorizontalStackLayout> ...
ViewModel:
public partial class CalendarPageViewModel : ObservableObject, INotifyPropertyChanged
{
private readonly CalendarService _calendarService;
[ObservableProperty]
private bool _isMonthActive;
[ObservableProperty]
private bool _IsListActive;
public ICommand SetMonthCommand { get; set; }
public ICommand SetListCommand { get; set; }
public CalendarPageViewModel(CalendarService calendarService)
{
_calendarService = calendarService;
SetMonthCommand = new Command(() =>
{
IsMonthActive = true;
IsListActive = !IsMonthActive;
}); // is not called when using IsEnabled at the XAML
SetListCommand = new Command(() =>
{
IsListActive = true;
IsMonthActive = !IsListActive;
}); // is not called when using IsEnabled at the XAML
} ....
You should use the CanExecute()
method, so that the button will be set to IsEnabled=false
based on the boolean property in your ViewModel. This way you only need one boolean whether the month or list is shown, also do not forget to call NotifyCanExecuteChanged()
on your command, so that it re-evaluates the CanExecute()
method. You can also use the handy RelayCommand
attribute from the CommunityToolkit.Mvvm nuget package.
[ObservableProperty]
private bool _IsListActive = true;
[RelayCommand(CanExecute = nameof(CanSetMonth))]
private void SetMonth()
{
IsListActive = false;
SetMonthCommand.NotifyCanExecuteChanged();
SetListCommand.NotifyCanExecuteChanged();
}
private bool CanSetMonth()
{
return IsListActive;
}
[RelayCommand(CanExecute = nameof(CanSetList))]
private void SetList()
{
IsListActive = true;
SetMonthCommand.NotifyCanExecuteChanged();
SetListCommand.NotifyCanExecuteChanged();
}
private bool CanSetList()
{
return !IsListActive;
}
To make the button look disabled, you could use the VisualStateManager
, which should be already in styles.xaml when you create a new MAUI project.
<Style TargetType="Button">
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
The xaml code:
<Button Text="Set Month" Command="{Binding SetMonthCommand}" />
<Button Text="Set List" Command="{Binding SetListCommand}" />