I've created a public bool LogedIn; in my login.cs:
if(login successful condition)
LogedIn = true;
else
LogedIn = false
But when I access this var from another form with Login Log = new Login();
by using if(Log.LogedIn) the LogedIn variable is always false, even after successful login by the user.
Why this is not working/updating its value outside its parent form?
Updating the code:
Login.cs
public bool isLogedIn;
private void button1_Click(object sender, EventArgs e)
{
if (i>-1 && (textBox2.Text == DS.Tables[0].Rows[--i][0].ToString()))
{
this.DialogResult = DialogResult.OK;
isLogedIn = true;
}
else
{
MessageBox.Show("Invalid password supplied for username \"" + comboBox1.Text + "\"", "Login Error.....", MessageBoxButtons.OK);
isLogedIn = false;
return;
}
}
Checking for the updated value in Home.cs
private void Home_Load(object sender, EventArgs e)
{
if (Log.isLogedIn) // Always False at this position.
{
label18.ForeColor = System.Drawing.Color.Green;
submitButton.Enabled = true;
}
else
{
label18.ForeColor = System.Drawing.Color.Red;
submitButton.Enabled = false;
}
}
I've checked again... I'm not having double instance of this variable in Login.cs form.
Here's how I'm calling Login.cs form via Home.cs (main form). Hope this helps...
private void loginToolStripMenuItem_Click(object sender, EventArgs e)
{
Log.FormClosed += new FormClosedEventHandler(Log_FormClosed);
Log.ShowDialog(this);
Log.BringToFront();
}
void Log_FormClosed(object sender, FormClosedEventArgs e)
{
if (Log.isLogedIn)
{
// Something here
}
else
{
// Something here
if (Log.DialogResult == DialogResult.Cancel)
Log.Hide();
}
}
I assume you have a form called Login in your application. Ignore the rest if assumption is wrong.
You are not referring to the correct instance of the Login form. In windows application, there is a collection called Application.OpenForms. This contains all the open form instances in your application. To access the correct Login form, try this:
Application.OpenForms.OfType<Form>().Where(x => x is Login).FirstOrDefault()
Make sure you have Login form always open to perform this task. You can make use of Hide instead of Close or CloseDialog for the Login form.
If you are closing the Login form, you can create static class which is accessible from each of the forms keep the properties there.
It seems that you have more than one instance of the Login class, each one with its isLogedIn var.
It is not clear where you are instantiating Login with your Login Log = new Login(); line. Have you tried to put a breakpoint there and see how many times it gets hit?
Another thing you could do is put a breakpoint on the line where isLogedIn is set, and another one where you read it. When the setting breakpoint is hit add a watch to the instance of Login (in this case add a watch to this) and choose Make Object ID from the right click menu. Your instance will be marjked by a "#1" Then do the same for the variable Log when the reading breakpoint is hit. If the mark is different (i.e. "#2") you can be sure that you are reading something different from the variable you set before.
Related
I'm writing an application that has a login form show prior to launching the main application. If the form is not allowed to load (the form checks for existing credentials and validates them, if successful the form is closed in the form_load event) then the application continues along swimmingly. However, if those credentials don't exist or are not correct then the form finishes loading and presents itself as a login form for the user.
When the user enters their information they then click a submit button which triggers a round of validation identical to above and then closes.
The login form does close (visibly) but never returns a result to the main program.
Main:
DialogResult result;
using (LoginForm lf = new LoginForm())
result = lf.ShowDialog();
if (result == DialogResult.OK)
{
Application.Run(new LibraryForm());
}
else
{
Application.Exit();
}
From the login form:
private void loginMaterialButton_Click(object sender, EventArgs e)
{
if (usernameTextBox.Text == "")
{
MessageBox.Show("You must enter a valid sharepoint user email for authentification!");
}
else if (passwordTextBox.Text == "")
{
MessageBox.Show("You must enter a valid sharepoint password for authentification!");
}
else
{
if (UpdateCredentials())
{
try
{
CloseOut();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private void LoginForm_Load(object sender, EventArgs e)
{
if (CheckExistingCredentials())
{
CloseOut();
}
}
private void CloseOut()
{
this.DialogResult = DialogResult.OK;
this.Close();
}
I made a second barebones LoginForm with only standard winform components and it worked as expected, however I'm not sure what the best course of action is to determine what exactly is causing the login form to not return on close?
Here is the github link for the package I'm using to wrap the winform:
https://github.com/leocb/MaterialSkin
Mystery solved:
https://github.com/leocb/MaterialSkin/issues/67
The issue is within this library, apparently something holds up the return of DialogResult when using the password characters in a ShowDialog form.
I have two forms, the main form which has a ListBox gets populated from the database and a login form. the first time the application run all the controls are disabled and when the user login successfully, the login form is closed and using the Activated event I enable the main form and the ListBox get populated, the problem with this approach is that every time the main form is not activated (e.g. minimized) and then activated, the event handler is called and the ListBox populated again even if the user has been already selected some items, they are unselected except the first item.
here is the login button event handler in the login form:
private void btnLogin_Click(object sender, System.EventArgs e)
{
if (VerifyUserNamePassword(txtUsername.Text, txtPassword.Text))
{
Frm_Main.auth = true; //auth field is used to check the authorization
Close();
}
else
MessageBox.Show("Wrong username or password.");
}
this is the Activated event handler in the main form:
private void Frm_Main_Activated(object sender, EventArgs e)
{
if (auth)
{
listBoxUsers.DataSource = ctx.Users.ToList();
listBoxUsers.DisplayMember = "UserName";
listBoxUsers.ValueMember = "Id";
logOffToolStripMenuItem.Enabled = true;
loginToolStripMenuItem.Enabled = false;
groupBox1.Enabled = auth;
}
I know that this is not the best way to accomplish it, but also I can't find an event that can be called immediately after closing the login form to reset the auth field other than the Activated event.
EDIT
As per Reza Aghaei comment I made it like this:
public bool Auth
{
set
{
if (value == true)
{
groupBox1.Enabled = true;
logOffToolStripMenuItem.Enabled = true;
loginToolStripMenuItem.Enabled = false;
listBoxUsers.DataSource = ctx.Users.ToList();
listBoxUsers.DisplayMember = "UserName";
listBoxUsers.ValueMember = "Id";
}
}
}
and called the Auth property in the login form:
Frm_Main main = new Frm_Main();
main.Auth = true;
Close();
But it doesn't work, the groupBox1 still disabled, the debugger passes through the setter but the form doesn't change!
I'm pretty sure I'm doing it wrong!
I am trying to enable admin privileges on my startup form. For this I've created an admin toolstrip login which would cause a password form to launch. I am however unable to update the startup form through the password form. I've seen a similar article over here [Why the controls not update, when call method from other form but this hasn't helped me solve my problem. My code is as below and what I have achieved so far is as below:
// Code for startup form...
public partial class StartupForm : Form {
private void adminToolStripMenuItem_Click(object sender, EventArgs e) {
FrmAdminPassword frmAdminPassword = new FrmAdminPassword();
frmAdminPassword.Show();
//this.Close();
//AdminLogin();
}
public void AdminLogin() {
loginToolStripMenuItem.Enabled = false;
logoutToolStripMenuItem.Enabled = true;
cmb1.Enabled = true;
btn1.Enabled = true;
tab1.Enabled = true;
tab2.Enabled = true;
tabControl1.TabPages.Add(tabAdminTasks);
MessageBox.Show("Admin Logged In");
}
}
// Code for password form
public partial class FrmAdminPassword : Form {
private void btnLoginAdmin_Click(object sender, EventArgs e) {
if (mskAdminPassword.Text == "password") {
StartupForm frm = new StartupForm();
frm.Show();
frm.AdminLogin();
this.Close();
}
else {
MessageBox.Show("Not a valid password");
this.Close();
}
}
}
If I implement it this way, what happens is that the original instance of the startup form is still present as a duplicate instance with all tabs and controls disabled and a new form is launched with all controls enabled.
What I actually want to achieve is:
Click on the adminToolStripMenuItem.
Launch the FrmAdminPassword.
Enter the password and hit Login on FrmAdminPassword.
After hitting Login, close the FrmAdminPassword and enable the controls on StartupForm.
Could someone please help on this? Thanks.
Use ShowDialog() to show your login form. This will stop the execution of code in the startup form until the login form closes
private void adminToolStripMenuItem_Click(object sender, EventArgs e)
{
// Putting the creation of the form inside a using block allows
// the automatic closing and disposing of the form when the code
// reaches the closing brace of the using block.
using(FrmAdminPassword frmAdminPassword = new FrmAdminPassword())
{
// This opens the frmAdminPassword form in modal mode, no
// code is executed after the call until you close the
// form with DialogResult.OK, DialogResult.Cancel or whatever
if(DialogResult.OK == frmAdminPassword.ShowDialog())
{
MessageBox.Show("Login executed with success!");
}
else
{
// Mo password given or form cancelled
// put here the logic to exit or disable things
}
}
}
Now in the Login form OK button click you could execute your logic to validate the password and to allow the closing of the form if the password match
public partial class FrmAdminPassword : Form
{
private void btnLoginAdmin_Click(object sender, EventArgs e)
{
if (mskAdminPassword.Text == "password")
this.DialogResult = DialogResult.OK;
else
{
MessageBox.Show("Not a valid password");
this.DialogResult = DialogResult.None;
}
}
}
To make this work you need to set the DialogResult property of the Login Form to something different from DialogResult.None. This Will force the Login form to automatically hide (not close) so you can read the DialogResult property on the initial instance of the startup form and decide what to do next. You should also provide some method to exit from the login form with DialogResult.Cancel and stop further processing because the user decided to not give a password.
Try this...
FrmAdminPassword
private void btnLoginAdmin_Click(object sender, EventArgs e)
{
if (mskAdminPassword.Text == "password")
{
this.DialogResult = System.Windows.Forms.DialogResult.OK;
}
else
{
MessageBox.Show("Not a valid password");
this.Close();
}
}
StartupForm
private void adminToolStripMenuItem_Click(object sender, EventArgs e)
{
FrmAdminPassword frmAdminPassword = new FrmAdminPassword();
using(frmAdminPassword)
{
if(frmAdminPassword.Show() == System.Windows.Forms.DialogResult.OK)
{
AdminLogin();
}
}
}
What is happening is that you have two separate copies of the form instantiated. At launch, the startup form is instantiated. During login, you are instantiating a totally new copy. Your login needs to reference the existing startup form.
Program.cs
using (Login login = new Login())
{
login.ShowDialog(); //Close this form after login is correct in login form button_click
}
if (isValiduser == true) //Static variable created in application to check user
{
Application.Run(new MainInterface());
}
Login form click event
private void btnLogin_Click(object sender, EventArgs e)
{
if(isValiduser == true)
{
this.Close();
}
else
{
//else part code
}
}
According to this code when we Click on Login event in Login form and isValiduser return true then Program.cs will run MainInterface form. but actually, this code is not run Application.Run(new MainInterface());
So, could anyone tell me what's wrong with this code?
Your code in Program.CS should be
using (Login login = new Login())
{
login.ShowDialog(); //Close this form after login is correct in login form button_click
if (isValiduser == true) //Static variable created in application to check user
{
Application.Run(new MainInterface());
}
}
And your login click event should be like that
private void btnLogin_Click(object sender, EventArgs e)
{
if(isValiduser == true)
{
//this.Close();
this.DialogResult = DialogResult.OK;
}
else
{
//else part code
}
}
problem is you are not set isValiduser as true in your code. so it will newer run MainInterface form.
Assume you have defined static variable called isValiduser in your Program.cs file as
static class Program
{
public static bool isValiduser = false;
[STAThread]
static void Main()
{
// rest of your code
And then when you click login button you need to set this variable based on login status.
you may need to have separate method for this.
private void btnLogin_Click(object sender, EventArgs e)
{
// call validate user method and set value to `isValiduser`
Program.isValiduser= IsValidUser("username", "password"); // here for testing i'm set it as true
if(Program.isValiduser== true)
{
this.Close();
}
else
{
//else part code
}
}
you can have method to validate users
private bool IsValidUser(string name, string pw)
{
return true; // impliment this method
}
What I suspect is happening is that when you get to the this.Close() the control goes back to the main thread and the application ends (if there is no further code after it). i.e Your program starts from the first line of the main and ends at the last. So if you open your login form first then you need to open the MainInterface form before closing the login form.
RESOLVED: Turned out to be a visual studio problem. Closed visual studio, cleaned and rebuilt, and the value started showing. Thanks all for the help, sounds like I need to switch to VS2010.
This may not be the best, safest, or preferred way to pass values between forms, but this is the way I am attempting for the moment. So, please do help me to get this way working. After you provide an answer, you're more than welcome to add in some better ways of doing this.
The problem is, when the modal dialog box closes and I go back to the owner, the textbox value from the modal is an empty string rather than the actual value. I've read in several places this should not be the case, as the data should persist even after the modal box disposes. Here's my code.
public partial class PreferencesForm : Form
{
public PreferencesForm()
{
InitializeComponent();
}
private void okButton_Click(object sender, EventArgs e)
{
if (masterRadioButton.Checked == true)
{
if (password1TextBox.Text != password2TextBox.Text)
{
errorLabel.Text = "Passwords do not match, please re-enter both passwords and try again.";
this.Refresh();
}
else if (password1TextBox.Text == "" && password2TextBox.Text == "")
{
errorLabel.Text = "You must enter a password.";
}
else
{
okResultButton_Click(null, null);
}
}
else if (singleRadioButton.Checked == true)
{
okResultButton_Click(null, null);
}
}
private void cancelButton_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Dispose();
}
private void okResultButton_Click(object sender, EventArgs e)
{
// invisible button
this.DialogResult = DialogResult.OK;
this.Dispose();
}
And here is the code that calls the above form as a modal dialog box.
private void setPreferencesToolStripMenuItem_Click(object sender, EventArgs e)
{
PreferencesForm pf = new PreferencesForm();
DialogResult result = pf.ShowDialog();
if (result == DialogResult.OK)
{
if (pf.password1TextBox.Text != "")
{
masterPassword = pf.password1TextBox.Text;
}
else
{
masterPassword = null;
}
}
}
Thanks for any assistance. I'm getting pretty frustrated over here. >:(
Note: The ReadOnly property of the password1TextBox variable is correctly shown as true or false, depending on what I select in the modal form, but the text property will still not correctly display.
I'm guessing that Dispose will also dispose the controls it contains. After the controls have been disposed, the text is likely no longer valid either. Try Close rather than Dispose and then Dispose in the caller.
You should listen to the people answering your question. Dispose is supposed to clear out memory allocated, it doesn't matter if you can still get the ReadOnly property.
Don't call Dispose in the form, call dispose from the calling code, as in the example code from the ShowDialog method documentation (http://msdn.microsoft.com/en-us/library/c7ykbedk.aspx#Y851). Note that Dispose is called just before the testDialog variable goes out of scope.
public void ShowMyDialogBox()
{
Form2 testDialog = new Form2();
// Show testDialog as a modal dialog and determine if DialogResult = OK.
if (testDialog.ShowDialog(this) == DialogResult.OK)
{
// Read the contents of testDialog's TextBox.
this.txtResult.Text = testDialog.TextBox1.Text;
}
else
{
this.txtResult.Text = "Cancelled";
}
testDialog.Dispose();
}
I propose just save the string of the control of your Dialog into string property, and retrieve value of that class property and not control's property value after Dialog is closed, and stop worrying about Dispose or not Dispose, or whatever else.
Hope this helps