C# Initializing form upon default text - c#

I have Form 1 With a label that has been set to "Company Name" by default.
CompanyNameLBL.Text
I placed a timer here so that if the database is not setup, then initialize Database Setup.
if (CompanyNameLBL.Text == "Company Name")
{
//Instantiating Timer Class
databaseTimer.Interval = 2000; // 1000 milliseconds
databaseTimer.Enabled = true;
databaseTimer.Tick += new EventHandler(dbTimer);
}
protected void dbTimer(object source, EventArgs e)
{
databaseTimer.Stop();
DatabaseSetup setupDatabase = new DatabaseSetup();
this.Hide();
setupDatabase.Show();
}
I have Form 2, which is my Database Setup. Once entering the right credentials, I can change the name of the label like this:
formLogin loginScreen = new formLogin();
loginScreen.CompanyNameLBL.Text = "a new company name";
loginScreen.Show();
It changes the label, but my timer still goes off. What gives?

The problem is here:
formLogin loginScreen = new formLogin();
You are creating a new formLogin instance, not a reference to the existing instance. You need to figure out how to communicate between the two forms. One option is to make the result of the login a property of the DatabaseSetup form, then pull that after closing the form:
databaseTimer.Stop();
DatabaseSetup setupDatabase = new DatabaseSetup();
this.Hide();
setupDatabase.Show();
loginScreen.CompanyNameLBL.Text = setupDatabase.CompanyName; // new property
this.Show();

I simply used
public formLogin(string dbName)
and passed it through that variable.

Related

Tabbed Menu - each tab as a separate CS file

I'm new to C# and have created a basic program.
My "Main menu" is setup with 7 tabs along the top.
I have set up CASE so when the user selects the tab it adds that specific submenu (frmXXXmenu) to the controls.
The issue is
Is this correct
Now each form will open each click, thus I keep generating instances of the forms (and I can see my process memory increasing!)
private void tabmain_SelectedIndexChanged(object sender, EventArgs e)
{
string curtab = tabmain.SelectedTab.Name.ToString();
switch (tabmain.SelectedTab.Name)
{
case "tabcollect":
frmcollectmenu frmcollectmenu = new frmcollectmenu();
frmcollectmenu.TopLevel = false;
tabcollect.Controls.Add(frmcollectmenu);
frmcollectmenu.Dock = DockStyle.Fill;
frmcollectmenu.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
frmcollectmenu.Show();
break;
case "tabpack":
frmpackmenu frmpackmenu = new frmpackmenu();
frmpackmenu.TopLevel = false;
tabpack.Controls.Add(frmpackmenu);
frmpackmenu.Dock = DockStyle.Fill;
frmpackmenu.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
frmpackmenu.Show();
break;
}
}
Etc for 7 tabs.
Am I in the right direction and if so, how do I fix this instance situation?
I was thinking either Dispose when no longer active.. or somehow not creating a new instance when one is already open?
Second issue
One of the forms takes about 2 seconds to open (it is showing a chart based on sql). How can i load this page in the tab when i open frmmain() to start the program and then when i open the tab it will be loaded?
I tried putting
frmcollectmenu frmcollectmenu = new frmcollectmenu();
frmcollectmenu.TopLevel = false;
tabcollect.Controls.Add(frmcollectmenu);
frmcollectmenu.Dock = DockStyle.Fill;
frmcollectmenu.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
frmcollectmenu.visible = false;
frmcollectmenu.Show();
(added the visible part) then i made it visible again when selecting the tab, but it seems it still takes a few seconds and doesnt really work right.
If you want only one instance of your forms opened then you should check the Application.OpenForms collection if one of your forms is already referenced there by the system
case "tabcollect":
frmcollectmenu f = Application.OpenForms["frmcollectmenu"];
if(f == null)
{
frmcollectmenu frmcollectmenu = new frmcollectmenu();
frmcollectmenu.TopLevel = false;
tabcollect.Controls.Add(frmcollectmenu);
frmcollectmenu.Dock = DockStyle.Fill;
frmcollectmenu.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
frmcollectmenu.Show();
}
else
f.Show();
break;
Notice that this works if you leave the name property of the form to its default name (same as the class name of the form)
You can also try to isolate the logic about your open forms in separate methods for each form and implement a dictionary where you store the tab key and the action to execute when the user select that particular tab
// At form global level....
Dictionary<string, Action> tabActions = new Dictionary<string, Action>()
{
{ "tabCollect", runCollect },
{ ..... },
so on for other tabs
}
// The logic for a particular form (the same are needed for others forms)
private static void runCollect()
{
frmcollectmenu f = Application.OpenForms["frmcollectmenu"];
if(f == null)
{
frmcollectmenu frmcollectmenu = new frmcollectmenu();
frmcollectmenu.TopLevel = false;
tabcollect.Controls.Add(frmcollectmenu);
frmcollectmenu.Dock = DockStyle.Fill;
frmcollectmenu.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
frmcollectmenu.Show();
}
else
f.Show();
}
Now you can remove the switch in your SelectedIndexChanged method and just select the appropriate action from the dictionary statically build at startup time of your main form
private void tabmain_SelectedIndexChanged(object sender, EventArgs e)
{
string curtab = tabmain.SelectedTab.Name.ToString();
if(tabActions.ContainsKey(curTab))
tabActions[curTab].Invoke();
}

Passing data w/ constructor with main form

I have three forms, f1, f2, f3 we'll call them. I have a class Account, in which I store username, password, groups and path (files). F2 is the main form, and should interact with both other forms. F1 is the login form and F3 is the edit form. I use this in my program.cs to call the login form before other forms.
Form1 login = new Form1();
if (login.ShowDialog() == DialogResult.OK)
{
Application.Run(new Form2());
}
To pass data between f2 and f3, I use a constructor with the account class. However, I would also like to pass data from f1 to f2, but if I use the same approach, I get no data interaction between the forms (data is null).
I edited the above code to this:
Form1 login = new Form1();
Account acc = new Account();
if (login.ShowDialog() == DialogResult.OK)
{
Application.Run(new Form2(acc));
}
In the login form (f1), I pass some data to the Account class, so upon login button click this happens:
private void LoginButton_Click(object sender, EventArgs e)
{
Account acc = new Account();
//some code
acc.Groups = "New group";
//some more code
DialogResult = DialogResult.OK;
}
Then, in the Form2.cs, I have the following code:
string groups = "";
public Form2(Account acc)
{
InitializeComponent();
groups = acc.Groups;
}
But whenever I run it like that, I never get any results in the main form (f2), acc.Groups is always null, and I do not know why exactly. I used the same approach with constructors to pull data from f2 to f3, and it worked fine, why doesn't this work? Is it because I use the wrong approach with the login form? What is the correct way to handle this?
the problem is that you create a new instance of Account in the LoginButton_Click event. and you never pass this instance to the form2!
Create a field in the Form1 class of type Account:
Account my_account;
And overload the constructor to take an account as parameter:
public Form1(Account acc)
{
my_account = acc;
}
then reference in the click event the field my_account
private void LoginButton_Click(object sender, EventArgs e)
{
//reference the class variable
my_account.Groups = "New group";
//some more code
DialogResult = DialogResult.OK;
}
In the beginning you need to pass the starting instance of Account into the Form1 constructor so it can be filled with values:
Account acc = new Account();
Form1 login = new Form1(acc);
if (login.ShowDialog() == DialogResult.OK)
{
Application.Run(new Form2(acc));
}
Explanation in detail:
When creating an instance of Account acc = new Account(); you get a unique object with a specific location in the memory. When you pass this object to the constructor of Form1 and assign it to the private field my_account you actually pass only the reference of acc. Meaning that you pass the location of it in memory. That means that when you do this: my_account = acc; in the constructor you make sure that my_account points to the same location as the acc object. When you manipulate values of my_account by assigning a string to Groups you actually manipulate the original acc object. After returning from Form1 you pass the acc object again as reference to the next constructor. So when you access in Form2 this object in groups = acc.Groups; you access the original location in memory that you have manipulated and to which you have assigned the string "New group".
In your posted code you created in Form1 an entire new object using Account acc = new Account(); which is again unique and independent of the object that you created in the very beginning. This object also is located on a different portion of memory as the first acc object. This is why the property Groups is null when you have tried to access it in Form2
I hope this is understanable
I see you create new Account() in two places ( so you have more than one instance), but you don't pass account to form2 nowhere.
You can make Account static like Janes suggest in comment or make property to get account.
In Form1, declare
public Account Account { get; set; }
In Account, declare
public Form1 Form1{ get; set; }
After created 2 objects login and acc :
Form1 login = new Form1();
Account acc = new Account();
Assign to each other
login.Account = acc;
acc.Form1 = login;

Static member inside the form

In my project on the WindowsForms, if I have a static instance inside the form, when I'm opening my form at the first time, it works. But if I'll close it and open again, the form will be empty. Why can it be?
public partial class Computer : Form
{
static Indicators indicators = new Code.Indicators();
}
P.S. I'm making it static, because I want to save it's value after the form will be closed.
Edit 1: Opening the form
private void button3_Click(object sender, EventArgs e)
{
Computer computer = new Computer();
computer.ShowDialog();
}
Edit 2: Computer Form
namespace WF
{
public partial class Computer : Form
{
static Code.Indicators indicators = new Code.Indicators();
public Computer()
{
if (indicators.isComputerAlreadyRunning == false)
{
InitializeComponent();
pictureBox1.Image = Properties.Resources.Computer1;
indicators.isComputerAlreadyRunning = true;
}
}
// My not successful try to save the value of the variable
public Code.Indicators ShowForm()
{
return new Code.Indicators(indicators.isComputerAlreadyRunning);
}
}
}
I don't think that static members work well with the Windows Form lifecycle.
I suggest you make Indicators a normal instance member of your form. To preserve state beyond the life of a form you can copy your state from the form and copy it back to the form when you open it.
// Keep this in the proper place
var indicators = new Code.Indicators();
...
// Copy back and forth for the life time of the form
using (var form = new Computer())
{
form.Indicators.AddRange(indicators);
form.Close += (s, e) =>
{
indicators.Clear();
indicators.AddRange(form.Indicators);
}
}
...
According to the constructor in the Computer class, the indicators.isComputerAlreadyRunning is set to true the first time the form is created.
So when Computer is created the second time, the if condition will fail and the whole if block will be skipped. That means your InitializeComponent(); won't get run and hence nothing in the form will shows up.
Put the InitializeComponent(); outside the if clause to make it work.

How can I send a value from form to another?

I have 2 projects in 1 solution first one to log into database second one have my main project my second project 'Class Library' Output.
I am trying send User Name from first project log in form to main project main form
I am using code
public string MyValue;
{
get { return txtUserName.Text; }
}
in log in window
and use
var frm1 = new DS4ERP .Core .Lanch .frmLogin ();
radLabel2.Text = frm1.MyValue;
i get nothing in second form
what is wrong ?
You are creating new Form instance. When you opening your second form use this:
Form2 f2 = new Form2(); // change Form2 with your second Form name
f2.Show(this);
Then change this code:
var frm1 = new DS4ERP.Core.Lanch.frmLogin ();
radLabel2.Text = frm1.MyValue;
To:
radLabel2.Text = ((frmLogin)Owner).MyValue;

C# VS: How to make the changes constant every time the form is loaded

I'm making a simple program using Visual Studio C#
The program is about Garage reservation system.
in the reservation form the user will choose a level from the drop down list and 10 labels will appear according to his request. User will click on the spot he needs (the label now will have a car image on it-means spot is reserved- ) then get the ticket.
My issue is when the user returns to home page and get back to the reservation form, and again choose the same level he chose before.. the labels will appear clean and empty as no one have reserved before.
My Question, what is the best way to make the label image and text changes and never return to its default every time the form is loaded?
I have declared two arrays of labels, and I have actually added 20 invisible labels.
public partial class Form3 : Form
{
Label[] level1 = new Label[10];
Label[] level2 = new Label[10];
and I assigned the labels in the constructor:
public Form3()
{
InitializeComponent();
label4.Click += new EventHandler(SpotChosen);
label5.Click += new EventHandler(SpotChosen);
label6.Click += new EventHandler(SpotChosen);
label7.Click += new EventHandler(SpotChosen);
label8.Click += new EventHandler(SpotChosen);
label9.Click += new EventHandler(SpotChosen);
label10.Click += new EventHandler(SpotChosen);
label11.Click += new EventHandler(SpotChosen);
label12.Click += new EventHandler(SpotChosen);
label13.Click += new EventHandler(SpotChosen);
label14.Click += new EventHandler(SpotChosen);
label15.Click += new EventHandler(SpotChosen);
label16.Click += new EventHandler(SpotChosen);
label17.Click += new EventHandler(SpotChosen);
label18.Click += new EventHandler(SpotChosen);
label19.Click += new EventHandler(SpotChosen);
label20.Click += new EventHandler(SpotChosen);
label21.Click += new EventHandler(SpotChosen);
label22.Click += new EventHandler(SpotChosen);
label23.Click += new EventHandler(SpotChosen);
level1[0] = label4;
level1[1] = label5;
level1[2] = label6;
level1[3] = label7;
level1[4] = label8;
level1[5] = label9;
level1[6] = label10;
level1[7] = label11;
level1[8] = label12;
level1[9] = label13;
level2[0] = label14;
level2[1] = label15;
level2[2] = label16;
level2[3] = label17;
level2[4] = label18;
level2[5] = label19;
level2[6] = label20;
level2[7] = label21;
level2[8] = label22;
level2[9] = label23;
}
Every time your form loads, labels are re-rendered and they take default values you set to them.
There are many techniques that you can preserve the last state of the controls you have.
Basically you need to store a flag of the labels state in memory when the reservation form is closed.
This can be done on the Form_unload event and one technique you could use is save them in a static Dictionary where the string key could be the label id, and the SomeFlagType is some type you are using to mark that this "Spot is reserved", if i didn't get you wrong. So your value could be a boolean flag, or even a value that you stored in your control that you want to preserve.
On the Form_Load event you can "query" the dictionary by your label's id and return the flag or value and apply it on the label.
In case it is a multi-user client-server environment, and you want to store your static dictionary on the server side for everyone to query, it would be a slightly different approach.
First of all, use a panel in your form (where you can put all your labels) so that you can add the event handlers to all the labels in this way :
foreach (Control c in Panel1.Controls)
{
c.Click += SpotChosen;
}
private void SpotChosen(object sender, EventArgs e)
{
var label = sender as Label;
}
And for saving the settings of your controls, I think you can use Properties.Settings.Default.Save(); http://msdn.microsoft.com/en-us/library/bb397755.aspx
First of all - Naming. So many labels with name labelN. It's easy to get mixed up. Also you do not need 23 times to set event handler, you can iterate through specific labels and assign one event handler for all of them. I suggest you to solve this mishmash with labels. Maybe you need to write UserControl also.
Second. Try to use patterns Singleton or State, or better to implement your windows forms application in MVC/MVP style. At least Singleton will be easiest solution for you.

Categories

Resources