NotifyCanExecuteChangedFor not working when added to an object in MAUI 8.0

114 views Asked by At

I am trying to disable an XAML button until the form is valid, at initial load it is disabled but not enabled on the model validation pass.

Here is my code

public class LoginRequest
{
    public string Email { get; set; }
    public string Password { get; set; }
}
public sealed partial class LoginViewModel : ObservableObject
{
    [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(LoginCommand))]
    private LoginRequest _form;
     
    bool IsFormValid()
    {
        return !string.IsNullOrEmpty(Form.Email) && !string.IsNullOrEmpty(Form.Password);
    }
     
    [RelayCommand(CanExecute = nameof(IsFormValid))]
    async Task Login()
    {
        //...
    }
}
    xmlns:vm="clr-namespace:MyProject.ViewModels.Account"
    x:Class="MyProject.Pages.Account.LoginPage"
    x:TypeArguments="vm:LoginViewModel"
    x:DataType="vm:LoginViewModel">
     
    <Entry Placeholder="Email"
        Text="{x:Binding Form.Email, Mode=TwoWay}">
    </Entry>
     
    <Entry Placeholder="Password"
        Text="{x:Binding Form.Password, Mode=TwoWay}">
    </Entry>
    
    <Button Text="Login" Command="{Binding LoginCommand}">
    </Button>

When I add individual properties at my ViewModel its working as expected but to an object.

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(LoginCommand))]
private string email;
    
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(LoginCommand))]
private string password;

What am I missing here?

1

There are 1 answers

0
Liqun Shen-MSFT On BEST ANSWER

Your code only modifies the Property of the Form instance instead of changing the value of Form itself.

So, if you want to get notified when a Property of an Object changes, you may try the following way,

First, also make the Email and Password to be an ObservableProperty.

public partial class LoginRequest :ObservableObject
{
    [ObservableProperty]
    public string email;

    [ObservableProperty]
    public string password;
}

Second, ObservableObject has a PropertyChanged EventHandler, which will occur when a Property has changed. So in your viewmodel, register and implement the PropertyChanged event handler for the Form instance.

    public MainPageViewModel()
    {
        Form = new LoginRequest();
        Form.PropertyChanged += Form_PropertyChanged;
    }

    private void Form_PropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        //this will invoke each time Email or Password change
        loginCommand.NotifyCanExecuteChanged();
    }

Hope it helps!