I'm developing an app and I want to include some global functionality like a couple of buttons that work for every Form that the app contains.
It is a MDI application which contains four child form, each form performs different tasks and each one has its own controls. I have a Clear and Search button on each form and what I'm trying to do is to create two global buttons that perform those actions for the form that is active at the moment.
For example, Form1 is the MDI parent and Form2 is a child of Form1. I call Form2 from a ToolStripMenuItem that is in Form1, I have a button in Form2 which clear all the textboxes in it. What I want to achieve is to move the code in this button to a button placed in a general bar in Form1 (MDI parent), in order to clear not only the textboxes for Form2 but for all the forms I have in my app.
This is what I've got so far:
//Form1 code
public partial class FrmPrincipal : Form
{
public FrmPrincipal()
{
InitializeComponent();
}
private void manageUsersToolStripMenuItem_Click(object sender, EventArgs e) //Calling Form2
{
FrmUserManager frmusers = new FrmUserManager();
frmusers.MdiParent = this;
frmusers.Show();
}
}
//Form2 code
public partial class FrmUserManager : Form
{
public FrmUserManager()
{
InitializeComponent();
}
}
private void BtnClear_Click(object sender, EventArgs e)
{
Clear(this);
}
private void Clear(Control all)
{
foreach (Control all in all.Controls)
{
if (all is TextBox) ((TextBox)all).Text = string.Empty;
if (all is CheckBox) ((CheckBox)all).Checked = false;
if (all is DataGridView) ((DataGridView)all).DataSource = null;
if (all.Controls.Count > 0) Clear(all);
}
}
So, basically what I want is to move this code to a button in Form1 to perform this action from outside Form2. If I can do it, I'll be able to get rid of the buttons I have in the four child forms (Search and Clear), and besides the app will be easier to use.
The only way I've thought of is to change the property "Modifiers" on each control in Form2 to "public" to try to access them from Form1 doing something like:
Form2 frm2 = new Form2();
if(frm2.Active == true) Clear(this);
In this case, I'd instantiate each form and verified if it's active.
It does not show up any error, but still it doesn't work. I guess I know why, the object created to call Form2 is a whole different object from the one created here, so the Form2 that is currently showing is not the same that it's been referenced here.
Does anyone understand what I'm trying to do?
Why don't you set your Clear function in Form2 public, then just do:
if(frm2.Active == true) frm2.Clear(frm2);
Or, if you want this for any of the forms, clearing the active one, you just move the Clear function to Form1, then do something like:
if(this.ActiveMDIChild != null)
Clear(this.ActiveMDIChild);
You have to keep track of your child forms when you create it. You may want to do something like this :
// In the MDI form
List<Form> mChildForms = new List<Form>();
void ToolStripButton_Click(object sender, EventArgs args)
{
Form myForm = new FrmUserManager();
...
mChildForms.Add(myForm);
}
void BtnClear_Click(object sender, EventArgs args)
{
foreach (Form f in mChildForms)
if (f.Active)
Clear(f);
}
May not be accurate, I do not have Visual Studio right now.
These are steps which I did to solve this problem.
1. Create class that inherits from Form and have public ClearData() method.
public class ClearableForm : Form
{
public void ClearData()
{
Action<Control> traverseControls = null;
traverseControls = (c) =>
{
if (c is TextBox) ((TextBox)c).Text = string.Empty;
if (c is CheckBox) ((CheckBox)c).Checked = false;
if (c is DataGridView) ((DataGridView)c).DataSource = null;
c.Controls.Cast<Control>().ToList<Control>().ForEach(traverseControls);
};
traverseControls(this);
}
}
2. Make your FrmUserManager so it inherits from ClearableForm.
public partial class FrmUserManager : ClearableForm
{
public FrmUserManager()
{
InitializeComponent();
}
}
3. Add "Clear" ToolStripMenuItem to the MenuStrip on your FrmPrincipal form with the following code.
private void clearToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (Form mdi_child in this.MdiChildren)
{
if (mdi_child is ClearableForm)
mdi_child.ClearData();
}
}
I hope it solves your problem. Cheers mate!
Related
Okay, this is a simple question, but it's been racking my brain for a while now.
I have two forms: Form1and Form2.
I have some checkboxes on Form2, and I want to use data from checked check boxes on Form2 on Form1 but when I add the following code on Form1 it's giving me errors:
if (cbTESTING.Checked)
{
uri_testings += string.Format("{0}.TESTINGS,", word);
}
I'm getting an error with cbTESTING as it's not referenced on Form1.
How can I use or reference checkboxes from Form2 in Form1?
I would do something like this:
Since Form1 creates Form2, and Form1 needs to manipulate Form2 then you can change this from Form2.Designer.cs:
private System.Windows.Forms.Checkbox cbTESTING;
To:
public System.Windows.Forms.Checkbox cbTESTING;
Assuming in Form1 you created Form2 like this:
Form2 f2 = Form2();
f2.Show();
Then you use this to check cbTESTING:
if(f2.cbTESTING.Checked) // do stuff ;
EDIT: I have seen your comment which says they do not relate to each other at all which makes it impossible to achieve in any easy method. What you said implies communication between these two THREADS since each Form runs in a Thread and these threads are unrelated. Communication is NOT an easy thing to do, you can try it using UDP and Events but trust me, having a direct relation between them would make things MUCH easier for you.
Anyway, I would assume some other Form or Thread would launch these Forms?
I managed to do this by making the checkboxes save values in the properties settings default and then calling them that way as every time i wanted to open the program instead of having to click them again it's auto saved my current values.
Thank you all for your help though.
Here is some code for future reference if anyone else wanted to do it the way I did.
Here is the code that saves it to the settings.
if (cbTESTING.Checked)
Properties.Settings.Default.cbTESTING = true;
else
Properties.Settings.Default.cbTESTing = false;
and here was the code to call that in a different form.
if (Properties.Settings.Default.cbTESTING == true)
{
uri_domains += string.Format("{0}.testing,", word);
}
Hope this will help someone in the future!
Here's a pretty clean way to fix this.. just change the access modifier to public for cbTESTING in the designer for Form2.
That is, in Form2.Designer.cs, change
private System.Windows.Forms.Checkbox cbTESTING;
to
public System.Windows.Forms.Checkbox cbTESTING;
Then, Form1 can look like this:
public partial class Form1 : Form
{
public Form1() {
InitalizeComponent();
Form2 secondForm = new Form2();
bool isChecked = secondForm.cbTESTING.checked;
}
}
Edits: removed protected solution, which isn't a great option in this case.
Here you have a ugly way to do what you want:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var frm = new Form2();
frm.ShowDialog();
label1.Text = frm.TextBoxChecked;
}
}
//Just declare a prop into Form2 a set it with the value you need
public partial class Form2 : Form
{
public string TextBoxChecked { get; set; }
public Form2()
{
InitializeComponent();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked)
TextBoxChecked = "Checkbox_1_checked";
else
TextBoxChecked = "Checkbox_1_unchecked";
}
}
Lets do things in a cool way.
Maybe a good aproache is to say to Form2: "Hey you, when your checkbox change let me know", It sounds like a callback. So let do it:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void doWhenCheckBoxChange(string text)
{
//I'm receiving the notification indicating that the checkbox has changed
label1.Text = text;
}
private void button1_Click(object sender, EventArgs e)
{
var frm = new Form2();
//I'm passing a callback to Form2, Here is where I say
//"Hey you, let me know where your checkbox change"
frm.DoWhenCheckboxChange = doWhenCheckBoxChange;
frm.ShowDialog();
//label1.Text = frm.TextBoxChecked;
}
}
public partial class Form2 : Form
{
//public string TextBoxChecked { get; set; }
public Action<string> DoWhenCheckboxChange;
public Form2()
{
InitializeComponent();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
//TextBoxChecked = "Checkbox_1";
//Notify to Form1 that checkbox has changed.
if (checkBox1.Checked)
DoWhenCheckboxChange("Checkbox_1_checked");
else
DoWhenCheckboxChange("Checkbox_1_unchecked");
}
}
If you test the second aproache, you will discover that you dont need to close your Form2 to see the changes.
Might not be the most elegant solution but will definitely work. Declare a public static bool variable in Form2. Add Checkbox changed event to your checkboxes and change those static variables accordingly. Then just check those variable in Form1 such as Form2.VariableName let me know if you need further explanation
Edit
In Form2 declare public static bool CheckBoxStatus = false; false by default, you can change that.
Also in Form2 add following event checkBox1.CheckedChanged += new EventHandler(CheckedChanged) and add appropriate function such as
private void CheckedChanged(object sender, EventArgs e)
{
CheckBoxStatus = checkBox1.Checked;
}
And Finally in Form1 one you can simply check if that checkbox is checked like this
if(Form2.CheckBoxStatus == true) ;
else ;
Hope that helps.
*PS sorry my formatting, new to posting answers here.
I hope the title is clear enough. Let me explain : I am doing a c# Winform App. When I start the app I have my Form 1 which starts, and I have other forms I can open from it by clicking buttons.
The problem is, I have functions in those Forms (Form 2, Form 3, Form 4..) I want to start from the Form 1 .
Currently here's my code
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// First Event, when I click in the toolstrip menu, I open the Form2 ("Ligne3")
private void ligne3ToolStripMenuItem_Click(object sender, EventArgs e)
{
var Ligne3 = new Ligne3();
Ligne3.Show();
}
Then, I have components in the Form2 (textboxs, buttons, functions etc)
public partial class Ligne3 : Form
{
public Ligne3()
{
InitializeComponent();
}
private void Ligne3_Load(object sender, EventArgs e)
{
//Some code
}
}
//Function I want to call from the Form1
public void send_email()
{
//Some code
}
How can I start my " send_email() " function from the Form1 (for example during Load Event) ?
Assign the values of Form2 or any other objects/variables to Linge3 object before calling show. Values which are needed in send_email() to be assigned before calling send_email(). Something like below.
private void ligne3ToolStripMenuItem_Click(object sender, EventArgs e)
{
var ligne3 = new Ligne3();
//define variables/properties in Ligne3 for all values to be passed
//then assign them with corresponding values
ligne3.Value1 = objForm2.Value1;
ligne3.Value2 = objForm2.Value2;
ligne3.Value3 = objForm2.textBox1.Text;
ligne3.Value3 = objForm2.checkBox1.Value;
//and so on
ligne3.send_email();
ligne3.Show();
}
If you are clicking a buttons on Form1, to start and open forms 2,3,4 etc, and in those btn_click handlers you are creating a new form2, 3,3,4. Then you will have a reference to each form and and can therefore just call the respective public method on the instance just created. eg
public class Form1
{
private Form2 subForm2;
private void OpenForm2_Click(object sender, eventargs e)
{
subForm2 = new Form2();
subForm2.Show()
}
private void sendEmailBtn_Click(object sender, EventArgs e)
{
subForm2.Send_email();
}
}
This are many things wrong with the above from a design point of view but i'm just using it to present the idea.
If you are creating the instance of Form2,3,4 etc outside of Form1's instantiation, then you would need some form of Constructor or property injection to provide the instance references.
Been stuck for quite a while reading similar posts here, I did find a solution but it was in dummy code and I just don't know what I'm doing wrong.
I have 2 forms, when the main form loads up I want to hide it and show form2 (the login form)
code looks like this.
private void Form1_Load(object sender, EventArgs e)
{
login loginform = new login();
loginform.Show();
this.Hide();
}
But when I run the program both forms are open and visible.
What am I doing wrong? Shouldn't the main form be hidden?
The Hide method does not have any effect from the Load event, since there isn't a handle created yet.
You have two options:
Using the Shown event (or better, the HandleCreated event) and hide it if a condition is met (like a variable 'logon form not shown')
Show the logon form as start form, then open the 'main' form. You can do this by passing an ApplicationContext around and pass on control to the main form.
You can do it with help of owner property, here is working example
Main form
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var loginFormMax = new LoginFormMax { Owner = this };//save main form as owner inside child form
loginFormMax.Show();
}
}
Child Form
public partial class LoginFormMax : Form
{
public LoginFormMax()
{
InitializeComponent();
}
private void LoginFormMax_Shown(object sender, EventArgs e)
{
var owner = this.Owner;
owner.Hide();//now you have control over owner form, just hide it
}
private void LoginFormMax_FormClosing(object sender, FormClosingEventArgs e)
{
var owner = this.Owner;
owner.Show();//now you have control over owner form, just show it again
}
}
I am trying to add a new item to a listbox in form1 from form2. The idea behind it is to end up with a list of different items each being different from each other (or the same, doesnt matter) based on the form2 activity. Say I open form1 (and it has shopping list (listbox))and I open form2 and click button which would add "bannana" to the list in form1. How do I do this? I've tryed various ways such as adding "addToList(parameter)" method in the form1 and then calling it from form2 and passing parameters but the list would remain empty however other things such as message box would pop up etc. So any ideas how to solve this?
I am using this method in form one to add the items into the list and it works:
public void addToList()
{
MessageBox.Show("Adding stuff to list");
listEvent.Items.Add("New item 1");
listEvent.Items.Add("new item 2");
MessageBox.Show("Done adding");
listEvent.Refresh();
}
Now when I try to call it from another class/form I use this:
public void changeForm()
{
EventPlanner mainEventForm = new EventPlanner();
mainEventForm.addToList();
}
Or:
private void btnAddEvent_Click(object sender, EventArgs e)
{
EventPlanner mainEventForm = new EventPlanner();
mainEventForm.addToList();
}
But it still doesnt work. Although when I use it from form1 (eventplanner, where the list is) it works perfectly fine. I even changed access modifyer to public so that shouldnt be the problem.
You can use a public Method on Form2 as I mentioned in my comment to your question. Here is a simple example.
Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
if (frm2.ShowDialog(this) == DialogResult.OK)
{
listBox1.Items.Add(frm2.getItem());
}
frm2.Close();
frm2.Dispose();
}
}
From2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
button1.DialogResult = DialogResult.OK;
button2.DialogResult = DialogResult.Cancel;
}
public string getItem()
{
return textBox1.Text;
}
}
When I run my application 2 different forms are loaded simultaneously,but one of them is shown.Now I want If one of these form is closed ,other form which is hidden should get closed also.Any Suggestion.
No Parent -Child relation between these forms.
Assuming that the two forms are both in the same process, you can have the second hidden form handle the FormClosed event of the visible form and close it self when the Visible Form's FormClosed event fires.
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
// The following does not need to happen in the Load of this form
// Create hidden Form
Form2 frm = new Form2();
// Attach hidden form to this form
frm.AttachTo(this);
}
}
public class Form2 : Form
{
public void AttachTo(Form frmMain)
{
frmMain.FormClosed += new FormClosedEventHandler(frmMain_FormClosed);
}
void frmMain_FormClosed(object sender, FormClosedEventArgs e)
{
this.Close();
}
}
I'm going to assume that this is one application with reference to both forms. Let me know if this is not the case.
Given this assumption, you have the following (shown in pseudocode):
MyApplication
{
Form form1;
Form form2;
}
Each of the form's Close events can close the other form if it is not already closed:
Form1_Close()
{
if(form2 != null)
{
form2.Close();
form2 = null;
}
}
and then:
Form2_Close()
{
if(form1 != null)
{
form1.Close();
form1 = null;
}
}
Does this meet your requirements?