Hello i have created 3 viewModels and want to connect them to a single View(UI) but can't

45 Views Asked by At

I have 3 viewModels (AdminViewModel, StudentViewModel, ProfessorViewModel) i have a UI where a user logs into a database,I have made a method called ExtractRole which takes the role of the user that is curerently logged in from a database.I am trying to make it after the user is logged his role is taken and based on the Role one of the three ViewModels is called and visualised.I don't know how to 'Bind' the ViewModel so it can be called

This is how i have made the LoginView.xaml.cs "

   public partial class LoginView : Window
{   
    private string _databasePath;

    public LoginView() 
        { 
          InitializeComponent(); _databasePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Welcome.db"); 
         }

    private bool isLoggedIn = false;
    private void LoginBtn_Click(object sender, RoutedEventArgs e)
    {
        // Perform validation against the database
        bool isValidUser = ValidateUser(LoginTextBox.Text, PasswordTextBox.Password);
        if (!isLoggedIn)
        {
            if (isValidUser)
            {
                // Navigate to the StudentsList page

                string role = ExtractRole(LoginTextBox.Text, PasswordTextBox.Password);

                MessageBox.Show($"Your role is: {role}");
                StudentsList studentsList = new StudentsList();
                // Add the StudentsList UserControl to a container (e.g., a Grid)
                // Assuming you have a Grid called "mainGrid" defined in your LoginView.xaml
                mainGrid.Children.Clear(); // Clear existing content
                mainGrid.Children.Add(studentsList);
                isLoggedIn = true;
                LoginBtn.Content = "Exit"; // Change button text to "Exit"
            }
            else
            {
                MessageBox.Show("Invalid username or password! Please try again!");
            }
        }
        else
        {
            isLoggedIn = false;


            // Optionally, you can open a new instance of the login window
            LoginView loginView = new LoginView();
            loginView.Show();
            // Close the current window
            Window.GetWindow(this).Close();
            LoginBtn.Content = "Login"; // Change button text to "Login"
        }

        // Prevent the button click event from bubbling up and closing the window
        e.Handled = true;
    }


    // Method to validate user credentials (dummy implementation)
    private bool ValidateUser(string username, string password)
    {
        
        // Construct the connection string to the SQLite database
        string connectionString = $"Data Source={_databasePath};";


        using (SqliteConnection connection = new SqliteConnection(connectionString))
        {
            connection.Open();

            // SQL query to check if the provided username and password exist in the Users table
            string query = "SELECT COUNT (*) FROM Users WHERE Name = @Name AND Password = @Password";

            // Create a command object with the query and connection
            using (SqliteCommand command = new SqliteCommand(query, connection))
            {
                // Add parameters to the query to prevent SQL injection
                command.Parameters.AddWithValue("@Name", username);
                command.Parameters.AddWithValue("@Password", password);

                long result = (long)command.ExecuteScalar();
                int count = Convert.ToInt32(result);
                connection.Close();
                return count > 0;
            }



        }
    }

    private string ExtractRole(string username, string password)
    {
        string role = null;
        string connectionString = $"Data Source={_databasePath};";
        using (SqliteConnection connection = new SqliteConnection(connectionString))
        {
            connection.Open();

            string query = "SELECT Role FROM Users WHERE Name = @Name AND Password =@Password";
            using (SqliteCommand command = new SqliteCommand(query, connection))
            {
                command.Parameters.AddWithValue("@Name", username);
                command.Parameters.AddWithValue("@Password", password);

                object roleObject = command.ExecuteScalar();

                if(roleObject != null) 
                {
                    role = roleObject.ToString();
                }
            }
        }

        return role;
    }
}

and this is for example my StudentViewModel: "

  namespace Welcome.ViewModel
    { 

public class StudentViewModel: UserViewModel
    { 

private Model.User _user;  

 public StudentViewModel(Model.User user) : base(user)
    {
        _user = user;
    }

    public StudentGradeStatus GradeStatus 
    {
        get {return _user.GradeStatus;}
        set{_user.GradeStatus = value; }
    }

    public DateTime BirthDay
    {
        get { return _user.BirthDay; }
        set { _user.BirthDay = value; }
    }

    public string FNomer
    {
        get { return _user.FNomer; }
        set { _user.FNomer = value; }
    }

    public UserGender Gender
    {
        get { return _user.Gender; }
        set { _user.Gender = value; }   
    }
  }

I tried using in the LoginView.xaml:

xmlns:local1="clr-namespace:Welcome.ViewModel;assembly=Welcome"

<Window.Resources> <DataTemplate DataType="{x:Type local1:AdminViewModel}"> <local1:StudentViewModel/> </DataTemplate>

but receive:" Severity Code Description Project File Line Suppression State Error XLS0414 The type 'local1:ProfessorViewModel' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built."

1

There are 1 best solutions below

0
Tomtom On

In your xaml you need to define the view which should be used if a specific viewmodel is provided. This looks like:

<DataTemplate DataType="{x:Type local1:AdminViewModel"}">
  <local1:MyViewForAll/>
</DataTemplate>
<DataTemplate DataType="{x:Type local1:StudentViewModel"}">
  <local1:MyViewForAll/>
</DataTemplate>
<DataTemplate DataType="{x:Type local1:ProfessorViewModel"}">
  <local1:MyViewForAll/>
</DataTemplate>

To display the content I would use a ContentControl which is bound to an object or to a base-class which all 3 different ViewModels share.

<ContentControl Content="{Binding CurrentViewModel}" x:Name="mainContent"/>

In your viewmodel or codebehind you can assign the correct ViewModelType to the ContentControl depending on what kind of users has logged in. This can look something like:

switch(role)
{
  case "admin":
    CurrentViewModel = new AdminViewModel();
    break;
  case "professor":
    CurrentViewModel = new ProfessorViewModel();
    break;
  case "student":
    CurrentViewModel = new StudentViewModel();
    break;
  default:
    throw new ArgumentException("case not found");
}