C# DialogForm opening when calling for mainForm - c#

I have a problem with my dialogForm. This is the code that opens my dialogForm (this is a login form) when my mainForm starts to run.
private void indexForm_Load(object sender, EventArgs e)
{
startForm loginForm = new startForm();
loginForm.ShowDialog();
indexUsername.Text = klasseGebruikersnaam.gebruikersnaam;
}
So when my indexForm (Main form) starts , it first loads a dialogForm, which is my login form.
Now my problem is that whenever I try to acces the mainForm from another form using this code (for example when I click a button):
this.Hide();
indexForm inf = new indexForm();
inf.Show();
The dialogForm pops up again. So I want to show my mainForm but , when I load my mainForm my dialogForm always pops up.
Any way around this?
Thanks in advance.

The problem is that you are loading your loginForm from your Main Form's Load event. Which is always going to fire after the constructor of the Main Form is called. Typically you will want to launch the loginForm from somewhere before the Main Form is loaded. You could do this in your Program.cs file and make it the main entry point of the program. Or just simply check if the user is already logged in.
Here is an example of both:
Program.cs
static void Main()
{
//Auto-generated code that VS writes for you
using (var loginForm = new LoginForm())
{
if (loginForm.ShowDialog() == DialogResult.Yes) //Presumably it would only return Yes if the login was successful.
{
Application.Run(new MainForm()); //Or however you call your main form
}
}
}
Of you can just put a property on the Main Form that determines if the user is logged in. Then you can call it in the Load event still.
Load Event
if(!this.UserLoggedIn)
{
loginForm.ShowDialog();
//Do something with the dialog result.
}
In my opinion it is better to user the Program.cs approach because if the user fails to login correctly, you can just exit or handle it as needed without loading your Main Form at all. The way you currently have it, the main form must load before the login form is shown, which could be problematic.

Well, you should remove that code from your main form and call it before showing the main form.
Or you could simply set a global variable that keeps the info for the current logged in user and, if that variable is not null, don't call again the login form
So, supppose that you login form prepare an instance variable of type LoggedinUser
public class LoggedinUser
{
public string NickName {get;set;}
public string UserRole {get; set;}
...
}
then in an utility class (or in your index form) you could have a static variable
public static LoggedinUser currentOperator = null;
in your in index_form you could write
if(GlobaClass.currentOperator == null)
{
using(startForm loginForm = new startForm())
{
if(loginForm.ShowDialog() == DialogResult.OK)
GlobalClass.currentOperator = loginForm.LoggedUser;
}
}

looks like you need to add a check to see if the user is logged in around the
loginForm.ShowDialog();
something like
if(!UserLoggedIn())
{
loginForm.ShowDialog();
}

Related

Close one form and display another

My app starts with a LoginForm where the user will enter their credentials. I need to close the LoginForm and display the DashboardForm. I'm able to do this:
public static bool OpenDashboardFormOnClose { get; set; }
public static bool OpenLoginFormOnClose { get; set; }
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
OpenDashboardFormOnClose = false;
OpenLoginFormOnClose = false;
Application.Run(new LoginForm());
if (OpenDashboardFormOnClose)
{
Application.Run(new DashboardForm());
}
if (OpenLoginFormOnClose)
{
Application.Run(new LoginForm());
}
}
The LoginForm login method:
Program.OpenDashboardFormOnClose = true;
this.Close();
The DashboardForm logout method:
Program.OpenLoginFormOnClose = true;
this.Close();
This works great when the user just logs in and then logs out.
The issue is that when a user has just logged out, and they try to log in again, the app closes instead of displaying the DashboardForm.
How do I achieve this? The user should be able to login and out as many times as they want...
Any help is appreciated.
I don't really recommend to use this approach of using many Application.Run one after another to show consecutive forms. That method starts the main message loop of the program, and generally is run once at program start and returns only once, at program exit.
Instead, make the forms open each other as needed, and leave the main message loop alone. Let's modify it to return to its almost default state:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Open the initial formm I'm assuming it's the login
LoginForm loginForm = new LoginForm();
loginForm.Show();
//Start the main message loop for the whole lifetime of the program
Application.Run();
}
Now, on the login form, when it's time to dismiss it and launch the main form, it does it itself instead of delegating:
//Close itself
this.Close();
//Launch the next form
DashboardForm dashboardForm = new DashboardForm();
dashboardForm.Show();
Similarly, on the dashboard when logging out you'll need to relaunch the login:
//Close itself
this.Close();
//Show the login again
LoginForm loginForm = new LoginForm();
loginForm.Show();
While all this work, this generates a problem not present before. As the main Application.Run isn't tied to a form, it won't stop running once the initial login exists, but only when explictly instructed to do so, with the net result of the process hanging after the window being closed.
To fix it, when it's time to close the application for good (not launch another form), call Application.Exit();, maybe in the Form.Closing event.
Just use a while loop to display the login and dashboard forms repeatedly. You won't need the "OpenLoginFormOnClose" flag anymore, but will need one to track whether the application should exit instead:
static class Program
{
public static bool OpenDashboardFormOnClose;
public static bool ExitApplication = false;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
while(!ExitApplication)
{
OpenDashboardFormOnClose = false;
Application.Run(new LoginForm());
if (OpenDashboardFormOnClose)
{
Application.Run(new DashboardForm());
}
}
}
}
Then add an "exit" button to your form(s) that does:
private void btnExit_Click(object sender, EventArgs e)
{
Program.ExitApplication = true;
this.Close();
}
So now the while loop will drop out and your program will end.
this.Close or Close just closes the current form, but if it's the main form it
closes all of them.
Application.Exit() Closes all the windows from the same program.
There is no possible way to just close the main form. if you do it all the windows
opened from it will close. You can only hide the form.
To hide the form, check the code below ▼
private void Example_Click(object sender, EventArgs, e)
{
this.Hide();
this.ShowInTaskbar = false;
}
if you're on the dashboard form, and want to close all remaining windows with/or from it use ▼
Application.Exit();
Another even simpler way many people don't use to open a form ▼
new DashBoardForm().Show();

How do i send a value from my first form to my main form in c#

Im making a little log in interface and im trying to send the user id after a succesfull login to my main form for safekeeping. I know how to do it from main to a secondary but i have no idea how to do it back. as im not creating a new Form main = new form();
public void btnLogIn_Click(object sender, EventArgs e)
{
UserClass existingUser = new UserClass();
existingUser.username = tbUsername.Text;
existingUser.password = tbPassword.Text;
result = databaseConnector.LogUSerIn(existingUser.username, existingUser.password);
if (result == 0)
{
MessageBox.Show("There aren't any registerd users with these credentials. Please try again or register below");
}
else
{
MessageBox.Show("Log in succesfull, Happy browsing!");
//Return value to Main form.
LogIn.ActiveForm.Close();
}
I would like the value result be send back to my main form. ive browsed the internet for about half an hour now and i only see from MAIN to SECONDARY but i can never find the reversed.
You can do it in a similar way like the OpenFileDialog does it.
Create a public property UserId in your login form and set the user id when the user logs in.
You can now access this property UserId in your main form after the ShowDialog() method of your login form has been called.
I can look something like this in your main form:
var loginForm = new LoginForm();
loginForm.ShowDialog();
var userId = loginForm.UserId;
// do something with the userId. maybe store it in a property of your main form.

Call a method on an already open form using differnat forms

I have been trying to solve this for a while now. I have checked simar posts but non of the sollutions seem to work.
My problem is that i'm trying to call the method 'Write' from a form called 'Log'.
public void ActivityLog(string LogString)
{
//Log what the system is doing for the user to see
if (LogAll == true)
{
//check if the error logging form is open
if (Application.OpenForms["Log"] != null)
{
//write to the log form
}
else
{
//the error log page is not yet open
Log LogFrm = new Log();
LogFrm.Show();
//now the form is open log the error
LogFrm.Write(LogString);
}
}
}
}
Now when i run the program and I call 'ActivityLog', the 'Log' form does open and the string I enter does appear, the second time I click the button the program goes to where i commented 'write to the log form'. But I cannot find a way to call the method from the aleady open form again.
The form 'Log' will stay open throughout the use of the program and will be added to from differant forms all calling the 'ActivityLog' method.
Any advice will be much appreciated.
Try something like this.
var LogFrm = Application.OpenForms["Log"] as Log;
if (LogFrm == null)
{
LogFrm = new Log();
LogFrm.Show();
}
LogFrm.Write(LogString);

Have only one instance of a subform open at a time c#

I'm writing an application that uses a wizard-like series of 5 simple forms. The first form, NewProfile, is opened from a menu item on the main application, MainForm, so is a subform of MainForm. The second form, TwoProfile, is opened from a button on NewProfile. The third form, ThreeProfile is opened from a button on TwoProfile, and so on for all 5 forms. Here is the sequence:
MainForm --> NewProfile <--> TwoProfile <--> ThreeProfile <--> FourProfile <--> FiveProfile. My problem is that when any form (NewProfile, TwoProfile, ThreeProfile, FourProfile or FiveProfile) is open, I don't want a user to be able to create an instance of NewProfile.
I started out by implementing a Singleton pattern, which half-way works. It works if NewProfile is open and I go to MainForm and try to create another instance of NewProfile. It does not work if NewProfile has been destroyed, by advancing to the next form and one of TwoProfile, ThreeProfile, FourProfile or FiveProfile is open. It tells me that NewProfile.IsDisposed is true, giving me a bad reference to the Singleton instance.
What I can't figure out is how to do my logic so that NewProfile won't be created if one of TwoProfile, ThreeProfile, FourProfile or FiveProfile is open or if NewProfile itself is open.
I hope this made sense. I don't really have much code to post, except what I did for my Singleton.
private static NewProfile _instance = null;
public static NewProfile Instance
{
get
{
if (_instance == null)
{
_instance = new NewProfile();
}
return _instance
}
}
Thank you :)
As suggested in the comments, each "form" could actually be a usercontrol you swap. That way, you only have one form and multiple pages. Alternatively, you can hide the form.
If you want multiple forms instead, then you could loop through all the open forms and see if the the ones you want to check are open. If not, you can open NewProfile.
bool shouldOpenNewDialog = true;
foreach (Form f in Application.OpenForms)
{
//give each dialog a Tag value of "opened" (or whatever name)
if (f.Tag.ToString() == "opened")
shouldOpenNewDialog = false;
}
if(shouldOpenNewDialog)
np = new NewProfile();
It's untested, but it should loop through all open forms and look for any that has a Tag saying opened. If it comes across one, then it set the shouldOpenNewDialog flag to false and NewProfile won't be called.
The way that we handle this is to have a static window manager class that keeps track of the open form instances. When the user performs an action that would cause a new window to open, we first check the window manager to see if the form is already open. If it is, we set focus on it rather than creating a new instance.
Every form that is opened inherits from a base form implementation that automatically registers itself with the window manager when it is opened and removes its registration when it is closed.
Here is a rough outline of the WindowManager class:
public class WindowManager
{
private static Dictionary<string, Form> m_cOpenForms = new Dictionary<string, Form>();
public static Form GetOpenForm(string sKey)
{
if (m_cOpenForms.ContainsKey(sKey))
{
return m_cOpenForms[sKey];
}
else
{
return null;
}
}
public static void RegisterForm(Form oForm)
{
m_cOpenForms.Add(GetFormKey(oForm), oForm);
oForm.FormClosed += FormClosed;
}
private static void FormClosed(object sender, FormClosedEventArgs e)
{
Form oForm = (Form)sender;
oForm.FormClosed -= FormClosed;
m_cOpenForms.Remove(GetFormKey(oForm);
}
private static string GetFormKey(Form oForm)
{
return oForm.Name;
}
}
And you can use it as follows:
Form oForm = WindowManager.GetOpenForm("Form1");
if (oForm != null)
{
oForm.Focus();
oForm.BringToFront();
}
else
{
oForm = new Form1();
WindowManager.RegisterForm(oForm);
// Open the form, etc
}

c# MDI parent form + login form error

I get this error:
Starting a second message loop on a single thread is not a valid operation. Use Form.ShowDialog instead.
When trying to exit my app after disposing a login form. To clarify, this is what I'm doing in my form:
public frmMainMDI()
{
InitializeComponent();
frmLogin frmLogin_ = new frmLogin(); //create new login form
frmLogin_.ShowDialog(); //show i
if (frmLogin_.DialogResult == DialogResult.Cancel) //if user pressed cancel
{
frmLogin_.Dispose(); //dispose login form
Application.Exit(); //Exit application. If I used this line, it throws the error stated above in Program.cs
//this.Dispose(); //If I try to use this one instead, it throws an 'already disposed' error
//this.Close(); //same error as .dispose
}
else
{
intCurrentLoggedInStaffID = frmLogin_.intStaffID;
}
}
And this is in my program.cs:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmMainMDI()); //this is the line that bugs out
}
I don't quite get it. It almost looks like the app is trying to restart itself when I try to .Exit it. Am I missing something pretty fundamental here? (I'm guessing the answer is 'yes')
I can't quite explain why you are getting this error, but I can suggest a better way to do it. If I understand your intentions correctly, you want to show a login form before the main MDI window is shown and exit your application, if the user pressed cancel in the login form.
Your program.cs:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
LoginForm loginForm = new LoginForm();
if (loginForm.ShowDialog() != DialogResult.Cancel)
{
MainMdiForm mainMdiForm = new MainMdiForm();
mainMdiForm.intCurrentLoggedInStaffID = loginForm.intStaffID;
loginForm.Dispose();
loginForm = null;
Application.Run(mainMdiForm);
}
}
Your constructor in the MainMdiForm should only contain the call to InitializeComponents.
You're attempting to exit the application (which means shut down the main message loop) in the middle of a constructor (which is bad in general) which is being run in the method which is supposed to be starting up that message loop in the first place. So you have contradictory operations going here.
What I would suggest is that you move your login form/dialog code into your program.cs/Main() function. So something like this:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using(frmLogin frmLogin_ = new frmLogin()) { //create new login form
frmLogin_.ShowDialog(); //show i
if (frmLogin_.DialogResult == DialogResult.Cancel) //if user pressed cancel
{
return; // This exits your application
}
}
Application.Run(new frmMainMDI()); //this is the line that bugs out
}

Categories

Resources