Home > OS >  How to get component by x:Name using Mvvm Pattern using .NET MAUI?
How to get component by x:Name using Mvvm Pattern using .NET MAUI?

Time:11-19

I am new using .NET MAUI and my issue is very simple but I could not find a way to solve this, I am trying to get any component by its x:Name using Mvvm pattern.

is it possible through ViewModels? For example I have a login page after clicking button I want this button to get blocked to prevent double clicks.

Login.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="Ventas_Citel.Views.Login.Login"
         xmlns:viewmodel="clr-namespace:Sales.ViewModels.Login"
         Title="">
<VerticalStackLayout 
   //... login page xaml form ...
   
    <Button Text="Log In" WidthRequest="200" CornerRadius="5" HorizontalOptions="Center" Command="{Binding LoginCommand}" x:Name="loginButton"/>

   //... login page xaml form ...
</VerticalStackLayout>

Login.xaml.cs

 using CommunityToolkit.Mvvm.ComponentModel;
 using CommunityToolkit.Mvvm.Input;
 using CommunityToolkit.Maui.Alerts;
public partial class Login : ContentPage
{
    public Login(LoginViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
    }
}

loginViewModel

 public partial class LoginViewModel : ObservableObject
    {
        [RelayCommand]
        async void Login()
        {
            if (!string.IsNullOrWhiteSpace(Email) && !string.IsNullOrWhiteSpace(Password))
            {

                // is there a way to call loginButton component?????
               // i need to disable it with loginButton.IsEnable = false;
                 loginButton.IsEnable = false // doesnt work loginButton doesnt exist

               // if there is any error i need to enable it again so the user can re enter
               // his/her credentials if it fails
                  loginButton.IsEnable = true;
            }

        }

}

How do I solve this?

CodePudding user response:

To solve this in correct MVVM manner, you have to add an additional property (for example IsLoginButtonEnabled) to your view model and just bind the button's IsEnabled property to it

ViewModel

public partial class LoginViewModel : ObservableObject
{
  private bool _isLoginButtonEnabled;
  public bool IsLoginButtonEnabled
  {
    get => _isLoginButtonEnabled;
    set
    {
       _isLoginButtonEnabled = value;
       PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( "IsLoginButtonEnabled" ) );
    }
  }

  [RelayCommand]
  async void Login()
  {
    if (!string.IsNullOrWhiteSpace(Email) && !string.IsNullOrWhiteSpace(Password))
    {
      this.IsLoginButtonEnabled = false;

      // if there is any error i need to enable it again so the user can re enter
      // his/her credentials if it fails
      
      // In order to enable the button again, just call ...
      //this.IsLoginButtonEnabled = true;
    }
  }
}

View

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     x:Class="Ventas_Citel.Views.Login.Login"
     xmlns:viewmodel="clr-namespace:Sales.ViewModels.Login"
     Title="">
<VerticalStackLayout 
   //... login page xaml form ...

  <Button Text="Log In" Command="{Binding LoginCommand}" IsEnabled="{Binding IsLoginButtonEnabled}" />

  //... login page xaml form ...
</VerticalStackLayout>

CodePudding user response:

I want to say something about your code:

  1. Do not try to access View elements in your ViewModel. Use bindings instead.

  2. If you gonna bind enabled, do not name the property for specific button. You don't want to handle it separately for each VisualElement. (Check out Value Convertors for reversal bool)

  3. This "isNullOrEmpty", can easily be replaced by TextValidationBehavior. And bind all this to a single bool. So you don't have to chain too many AND checks.

  • Related