1

How do I do a Login from one Window to another Window in order for me to get the user's details after the login?

I know that "a ViewModel shouldn't know anything about the View", but I really haven't found an "MVVM way" to do this.

I Login my User like this:

LoginViewModel:

class LoginWindowViewModel : BaseViewModel
{
    private readonly UserAccountRepository _userAccountRepository;
    public event EventHandler Closed; //The Window (LoginWindow) closes itself when this event is executed

    public LoginWindowViewModel() //constructor
    {
        _userAccountRepository = new UserAccountRepository();
        CurrentUserAccount = new UserAccount();
        LoginCommand = new DelegateCommand(Login);
    }

    public UserAccount CurrentUserAccount { get; set; }
    public ICommand LoginCommand { get; }

    private void Login()
    {
        if (TextboxAndPasswordboxIsNotBlank())
        {
            UserAccount userToLogin = _userAccountRepository.Get(CurrentUserAccount.Username); //CurrentUserAccount.Username is binded to a Textbox in the UI
            
            //This is a view (and it is now involved in the ViewModel)
            MainWindow mainWindow = new(userToLogin); //I passed my user details to the MainWindow here
            
            //this shows my MainWindow
            mainWindow.Show();
            //and closes the LoginWindow
            Close();
        }
    }
    
    //The method that executes Closed EventHandler
    private void Close() 
    {
        Closed?.Invoke(this, EventArgs.Empty);
    }
}

I set the DataContext of my MainWindow at the code-behind:

public partial class MainWindow : Window
{

    /*
      If I set the DataContext at the xaml (Window level) like this:
      d:DataContext="{d:DesignInstance Type=windows:MainWindowViewModel}"
      
      I will not be able to get the current logged in user, that's why I set the DataContext here at the code-behind
    */
    readonly MainWindowViewModel _viewModel;

    //I pass the UserAccount here so that the MainWindow's ViewModel can USE the LOGGED IN User's details
    public MainWindow(UserAccount currentUserAccount)
    {
        InitializeComponent();
        _viewModel = new MainWindowViewModel(currentUserAccount);
        DataContext = _viewModel;
    }
}

This is the MainWindow's ViewModel (MainWindowViewModel):

public class MainWindowViewModel : BaseViewModel
{
    private readonly UserAccountRepository _userAccountRepository;
    public ICommand UpdateCurrentUserCommand { get; } //used in UserAccountView
    public ICommand DeleteCurrentUserCommand { get; } //used in UserAccountView

    public ICommand DashboardViewCommand { get; }
    public ICommand ProfileViewCommand { get; }

    public DashboardViewModel DashboardVM { get; set; }
    public UserAccountViewModel ProfileVM { get; set; }

    public object CurrentView { get; set; }
    public UserAccount CurrentUserAccount { get; set; }

    public MainWindowViewModel(UserAccount currentUserAccount) //now I can get the current logged in UserAccount through this
    {
        CurrentUserAccount = currentUserAccount;
        _userAccountRepository = new UserAccountRepository();

        UpdateCurrentUserCommand = new DelegateCommand(Update);
        DeleteCurrentUserCommand = new DelegateCommand(Delete);

        DashboardVM = new DashboardViewModel();
        ProfileVM = new UserAccountViewModel();

        CurrentView = DashboardVM; //This is managed by a ContentControl in the MainWindow

        //This is for navigating through different views
        DashboardViewCommand = new NavigationCommand(o => { CurrentView = DashboardVM; });
        ProfileViewCommand = new NavigationCommand(o => { CurrentView = ProfileVM; });
        
        Get();
    }

    public void Get()
    {
        UserAccount userAccount = _userAccountRepository.Get(CurrentUserAccount.Username);
        //Some Logic
    }
    public void Update()
    {
            bool idExists = _userAccountRepository.IdExistsInDatabase(CurrentUserAccount.Id);
        //Some Logic
    }
    private void UpdateCurrentUser()
    {
        bool isUpdate = _userAccountRepository.Update(CurrentUserAccount);
        //Some Logic
    }
    public void Delete()
    {
            bool isDeleted = _userAccountRepository.Delete(CurrentUserAccount.Id);
        //Some Logic
    }
}

A problem arises because of this login system. I can't use the MainWindowViewModel as a DataContext for the MainWindow and the UserAccountView. I asked a question here, and I think that making my "Login system" like this causes this problem. (It turns out that I need a shared ViewModel to solve my problem (My ultimate goal here is to update the sidebar username, if the username gets updated in the UserAccountView)

paraJdox1
  • 805
  • 9
  • 23
  • 1
    What you need is a Shared State. You can check out Mediator Pattern for creating a shared state for MVVM pattern. – Eldar Jun 02 '21 at 07:25
  • yeah, I did the *common* viewmodel here is the MainWindowViewModel, where is houses my MainWindow navigations and the commands for my UserAccountView. but I can't seem to bind my UserAccountView to the MainWindowViewModel's DataContext, even if I removed all the code for my UserAccountViewModel and also removing any explicit DataContext (in xaml and in code-behind) – paraJdox1 Jun 02 '21 at 07:26

0 Answers0