theStig
theStig

Reputation: 610

NavigateCommand only called once

In order to familiarize myself with MVVM for WinRT I have been looking at the example MvvmLight WinRT project. Currently I'm running into an issue where my RelayCommand is only called once (on construction of viewmodel). What I want to do is go to the MainViewModel if the user is authorized. If I remove the conditional check of the login in the LoginCommand method, the RelayCommand works as expected. Any thoughts as to what I'm doing wrong? Should I not being doing my validation within the LoginCommand?

LoginViewModel (some code has been removed):

public class LoginViewModel : ViewModelBase {
  private readonly IDataService _dataService;
  private readonly INavigationService _navigationService;

  private RelayCommand _navigateCommand;
  private Login login; //contains username and password

  /// <summary>
  /// Gets the NavigateCommand.
  /// THIS DOES NOT GET FIRED UPON BUTTON CLICK
  /// </summary>
  public RelayCommand LoginCommand{
     get {
        if (login != null && login.UserName.Equals("Test"))
           return _navigateCommand ?? (_navigateCommand = new RelayCommand(() => _navigationService.Navigate(typeof(MainPage))));
        return _navigateCommand;
     }
  }

LoginPage.xaml.cs (some code has been removed):

public sealed partial class LoginPage {
  public LoginViewModel Vm {
     get { return (LoginViewModel)DataContext; }
  }

  public LoginPage() {
     InitializeComponent();
  }

  protected override void LoadState(object state) {
     var casted = state as LoginPageState;

     if (casted != null) {
        Vm.Load(casted);
     }
  }

  protected override object SaveState() {
     return new LoginPageState {
        Credentials = new Login {
           UserName = txtUserName.Text,
           Password = txtPassword.Text
        }
     };
  }

  public class LoginPageState {
      public Login Credentials { get; set; }
      }
  }
}

LoginPage.xaml (some code has been removed)

<Button Content="Login"
            x:Name="NextPageButton"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Margin="10"
            Command="{Binding LoginCommand}" />

Upvotes: 1

Views: 150

Answers (1)

venerik
venerik

Reputation: 5904

The problem is the condition. When your LoginPage loads, it tries to bind your Button to the LoginCommand. In order to achieve that, it gets the LoginCommand from your ViewModel. At that point in time Login is null and therefore the property will return _navigateCommand which is null. After that the page will not try to use the LoginCommand because it already knows its value.

To solve this you could move the condition inside the lambda expression:

public RelayCommand LoginCommand
{
    get
    {
        return _navigateCommand ?? (_navigateCommand = new RelayCommand(
            () =>
            {
                if (login != null && login.UserName.Equals("Test"))
                {
                    _navigationService.Navigate(typeof(MainPage));
                }
            }));
    }
}

An even better solution would be to move the authorization to another class. Something like:

public RelayCommand LoginCommand
{
    get
    {
        return _navigateCommand ?? (_navigateCommand = new RelayCommand(
            () =>
            {
                if (_authorizationService.UserAuthorized(login))
                {
                    _navigationService.Navigate(typeof(MainPage));
                }
            }));
    }
}

Hope this helps.

Upvotes: 1

Related Questions