Toggle and communicate between two Windows forms in Visual C#? - c#

I have two forms in my Windows Form Application, a main and a login info form.
The main form has a button which opens the login info form on being clicked. The login info form gets displayed as a new form on the main window with the main window also being visible in background while the user enters login info. If the login info is correct the login form should close while the main form should display the string "Welcome" and the correct username from login form. Now the issue is that after entering the correct login info on the login form and clicking the Login button, a new window of the main form appears with the previous main form also running as shown in the figure..
How can I make the previous instance of main form close and get the correct text displayed? Any help is appreciated.
I am using the following codes for creating and opening the main and the login info forms.
Code snippet of main form:
public partial class Main_Form : Form
{
private string u_name = "";
public Main_Form(string username)
{
InitializeComponent();
u_name = username;
label1.Text = label1.Text + " " + u_name;
}
private void Loginbutton_Click(object sender, EventArgs e)
{
Form Form2 = new login_Form();
Form2.ShowDialog();
}
}
Code snippet of login form:
public partial class login_Form : Form
{
public static string username = "";
public login_Form()
{
InitializeComponent();
}
private void Button_Login_Click(object sender, EventArgs e)
{
if (textBox_Login.Text == "Admin" && textBox_Password.Text == "123")
{
this.Hide();
username = textBox_Login.Text;
Form Form1 = new Main_Form(username);
Form1.ShowDialog();
}
else
{
MessageBox.Show("Please Enter Username and/or Password Again!");
}
}
}

You shouldn't have 2 instances of MainForm, just use one and update as required.
In your mainform you should call the LoginForm and check the DialogResult (I will explain this later).
So here, if you get an OK result it means the Login worked, otherwise the user cancelled.
So in MainForm change the constructor to be empty and remove the u_name parameter
public Main_Form()
{
....
}
private void Loginbutton_Click(object sender, EventArgs e)
{
Form Form2 = new login_Form();
if(Form2.ShowDialog() == DialogResult.OK) //We call LoginForm and wait for a Result
{
//Login was successful. Then we can set the label to the username, which is now a property for Login Form (see below)
label1.Text = Form2.UserName;
}
else
{
//Login was cancelled
//You must now implement logic to handle this case
}
}
Now in the Login form you want to check login and return the dialog result to the MainForm. DialogResult is, as the name suggests, the result of calling the LoginForm Dialog.
You will also need another click event for the cancel button.
public partial class login_Form : Form
{
//username is changed to a property
public string Username { get; private set; }
public login_Form()
{
InitializeComponent();
}
private void Button_Login_Click(object sender, EventArgs e)
{
//The check remains as before.
if (textBox_Login.Text == "Admin" && textBox_Password.Text == "123")
{
//If successful, we set the dialogresult, username and close this form.
this.Username = textBox_Login.Text;
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
//Otherwise we handle the error
MessageBox.Show("Please Enter Username and/or Password Again!");
}
}
//The new click event for the cancel button
private void Button_Login_Cancel(object sender, EventArgs e)
{
//We set the dialogresult to cancel (could be anything else) and close
this.DialogResult = DialogResult.Cancel;
this.Close();
}
}

Related

How do I make the main form show only if the user login is successful from a second form?

I am trying to make a form that verifies user login. I want that form to show first then, if the user login is successful, the main form should show.
this is what I have tried(in the second form):
private void button1_Click(object sender, EventArgs e)
{
string funame = "thename";
string dep = "thedep";
string unm = "theusername";
string ups = "thepassword";
User cs = new User(funame, dep, unm, ups);
if (cs.validateLogin(unm, ups));
{
MessageBox.Show("Welcome " + funame + " of " + dep);
frmPurchaseDiscountedItem fpd = new frmPurchaseDiscountedItem();
fpd.Show();
}
}
The problem is the main form always pops out first.
It should be something like:
*2nd form pops up then, if user is verified, main form pops up
Here is a workaround.
You don't need to change "start form" in Program.cs. You can open the main window at the beginning and hide it. Then create a Login instance and show it.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
Login login = new Login(this);
// hide MainForm
this.Hide();
// show Login
login.ShowDialog();
}
}
If login button in Login form clicked, show the MainForm and close Login form.
public partial class Login : Form
{
private MainForm mainform = null;
public Login(MainForm main)
{
InitializeComponent();
// get MainForm instance
this.mainform = main;
}
// if success
bool success = true;
private void btnLogin_Click(object sender, EventArgs e)
{
if(success) // check login here
{
// show main form
mainform.Visible = true;
// close login form
this.Close();
}
}
}
In addition, if you click the X button in the upper right corner of the Login form, it will also show the hidden MainForm (if user doesn't want to login, close the application). We can avoid it by overriding WndProc.
protected override void WndProc(ref Message msg)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;
if (msg.Msg == WM_SYSCOMMAND && ((int)msg.WParam == SC_CLOSE))
{
// click the 'X' button to close the application
Application.Exit();
return;
}
base.WndProc(ref msg);
}

C# WinForms. Enable control from another class

In my program, I have two forms: public partial class Form1 : Form,
and a log-in form: public partial class Login : Form. Both within the same namespace
Login window is opened when a Log-in button is clicked on the main window:
public partial class Form1 : Form
{
private void LoginToolStripMenuItem_Click(object sender, EventArgs e) //Login button event
{
LoginWindow = new Login();
LoginWindow.ShowDialog();
LogOutToolStripMenuItem.Enabled = true;
}
}
When the password is entered, I want to enable additional controls for the user, on the main screen.
groupBox2 is invisible by default, now I would like to make it visible:
public partial class Login : Form
{
public Login()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e) //Confirm click event
{
if (textBox1.Text == Form1.password) //Here, no trouble accessing a string from the main screen
{
Form1.groupBox2.Visible = true; //********** Here is my problem **********
Form1.LoginWindow.Close();
}
else
{
textBox1.Text = "Incorrect password";
textBox1.SelectAll();
}
}
}
How do I overcome "An object reference is required for the non-static field, method or property 'Form1.groupBox2' problem?
All my controls are already set to public.
I'm reading and reading and can't figure it out, it's driving me mad now.
I'm not expecting a ready solution, just a good explanation.
You can just raise a event on your login form like this:
public partial class Login : Form
{
public EventHandler OnPasswordDone; // declare a event handler
public Login()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text == Form1.password)
{
// raise the event to notify main form
OnPasswordDone(this, new EventArgs());
}
else
{
textBox1.Text = "Incorrect password";
textBox1.SelectAll();
}
}
}
And in your main form:
public partial class Form1 : Form
{
private void LoginToolStripMenuItem_Click(object sender, EventArgs e) //Login button event
{
LoginWindow = new Login();
LoginWindow.OnPasswordDone += Login_PasswordDone; // regist your event here
LoginWindow.ShowDialog();
LogOutToolStripMenuItem.Enabled = true;
}
private void Login_PasswordDone(object sender, EventArgs e)
{
//Do what you need to do here like:
groupBox2.Visible = true;
}
}
Since Form1 is not static class , so you should create object of this class then set visible to true like as
Form1 formobj=new Form1();
formobj.groupBox2.Visible = true;

How do I get information from a closed window in App.xaml.cs?

I have multiple windows. My LoginWindow has to validate the user. If this window is canceled the complete application should shutdown. If the user enter the correct login, the LoginWindow should be closed and the MainWindow open.
Question:
My problem is at the yellow diamond: How to determine the state of the login process?
That is my current state.
public partial class App : Application
{
[STAThread]
public static void Main()
{
var app = new App();
var login = new LoginWindow();
if (app.Run(login) == 1) //<-- Problem: How to get the state from login?
{
var mainapp = new MainWindow();
app.Run(mainapp);
}
}
}
I tried to get an exitcode from the loginwindow by using Application.Current.Shutdown(1); but it cause an InvalidOperationException on app.Run(mainapp);, because Shutdown closes the complete application.
Environment.Exit() terminates this process and gives the underlying operating system the specified exit code.
But a window has no "return value". You could handle the Closed event for the LoginWindow and check whether a property of thw window itself, or its view model, has been set. Please refer to the following example.
public class Program
{
private static readonly App app = new App() { ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown };
[STAThread]
public static void Main()
{
LoginWindow login = new LoginWindow();
login.Closed += Login_Closed;
app.Run(login);
}
private static void Login_Closed(object sender, EventArgs e)
{
LoginWindow loginWindow = (LoginWindow)sender;
loginWindow.Closed -= Login_Closed;
if (loginWindow.LoggedIn)
{
MainWindow mainWindow = new MainWindow();
app.MainWindow = mainWindow;
app.ShutdownMode = System.Windows.ShutdownMode.OnMainWindowClose;
mainWindow.Show();
}
}
}
public partial class LoginWindow : Window
{
public LoginWindow()
{
InitializeComponent();
}
public bool LoggedIn { get; private set; }
private void Login_Click(object sender, RoutedEventArgs e)
{
//if (authenticate)...
LoggedIn = true;
Close();
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
LoggedIn = false;
Close();
}
}
I found a smart solution. A Window with return value is called "Dialog".
App.xaml.cs
[STAThread]
public static void Main()
{
var app = new App() { ShutdownMode = ShutdownMode.OnExplicitShutdown };
if (new LoginWindow().ShowDialog() ?? false == true)
app.Run(new MainWindow());
}
LoginWindow.xaml.cs
private void OnLoginClick(object, EventArgs)
{
this.DialogResult = true;
}
private void OnCancelClick(object, EventArgs)
{
this.DialogResult = false;
}
To exit the whole application use "Application.exit();" and to open the main windows create object of that form then use "object.Show()" and "this .hide()" to hide the login form.
For example:
Assume the query i.e. stored procedure like:
Create procedure dbo.usercheck
(
#userid nvarchar,
#password nvarchar
)
As
Select username from login table
C# code:
SqlCommand com=new
SqlCommand("dbo.usercheck","connection");
If(com.executescalar()==null)
{
Application.exit();
}
else
{
Mainform f=new Mainform();
f.show();
this.hide();
}
You can write the "Application.exit();" statement in cancel button's click event to close the application whenever you want to close whole application when clicked on cancel button of login form.
When user enters wrong user id or password then you can show the error message instead exit the application.
I would use the following code:
Declare a bool variable to check if user closed the app or if it was closed from your code:
bool userClosedForm = false;
Then inside the Close button add this line, after the code you already had there:
private void btnClose_Click(object sender, EventArgs e)
{
//your code
userClosedForm = true;
}
Add a Form_Closed event where you check the value of the variable:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (userClosedForm == true) Application.Exit();
else
{
//your code to open the next form if the user logged in and you closed the form from code
}
}
Hope this helps ^^

Share an instance of a object between windows technique

I have a wpf application with a MainWindow and the user click a login button that open a new window i created. in that new window.cs file i have the user type in username which is stored in a new instance of the user class. I want to have that username (stored in the new instance of the class) accessible in the MainWindow.cs
whats the best practice for this?
You can always expose that through a public property on the login form, much like with OpenFileDialog :
void Login()
{
var login = new LoginForm();
if (login.ShowDialog() == DialogResult.OK)
{
var userName = login.UserName;
}
}
public class LoginForm : Form
{
public string UserName { get; private set; }
public void OnOKButton_Click(object sender, EventArgs e)
{
// validation...
this.DialogResult = DialogResult.OK;
this.UserName = UserNameTextBox.Text;
this.Dispose();
}
}

how to check if a non-modal dialog is already launched

My application launches a non-modal dialog on a button click. If user clicks on that button again, I would like to do a check if that form is already running and wonder if its possible?
You can use Application.OpenForms Property
if (Application.OpenForms.OfType<YourNonModalFormType>().Any())
// one is already opened
If you want to close this form:
var form = Application.OpenForms.OfType<YourNonModalFormType>().FirstOrDefault();
if (form != null)
{
// launched
form.Close();
}
Another approach is to manually declare a variable to track your form instance:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Form2 f2 = null;
private void button1_Click(object sender, EventArgs e)
{
if (f2 == null || f2.IsDisposed)
{
f2 = new Form2();
f2.Show();
}
else
{
f2.Close();
}
}
}

Categories