I'm using a container (mdi parent) to open up a main menu. The main menu allows the user to connect to a database and open other programs. I'm trying to display what database you are connected to on the container (parent form) but i'm having issues passing the string from main menu to the container. When the user clicks the connect button, I somehow need the container to have an event listener to listen for a button click from the child form. When the connect button is clicked on the child form, it will pass the variable to the parent. How would I go about doing this?
Maybe you can use an event. So each time the database name changes on the child form you can get a call back on the parent form
Child
public partial class Child : Form
{
public event DatabaseChangeHandler DatabaseChanged;
public delegate void DatabaseChangeHandler(string newDatabaseName);
public Child()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//When the database changes
if (this.DatabaseChanged != null)
{
this.DatabaseChanged("The New Name");
}
}
}
Parent
public partial class Parent : Form
{
private Child childForm;
public Parent()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Open the child form
childForm = new Child();
childForm.DatabaseChanged += childForm_DatabaseChanged;
childForm.ShowDialog();
}
void childForm_DatabaseChanged(string newDatabaseName)
{
// This will get called everytime you call "DatabaseChanged" on child
label1.Text = newDatabaseName;
}
}
Just declare a public variable Eg: var1 in Form2 and on selection of rows from Grid assign the selected value to the Form2 public variable var1.
Then Once you close the Form2. You can access the values in Form1 by say you have a textbox in Form1 which should get the selected value from grid of Form2 by mentioning as
Form2 f2=new Form2();
TextBox1.Text=f2.var1;
Hope this helps
Related
The parent Window Forms button mouse move event is getting correctly into the status bar label of the child window form ... but the opposite of that is not working means "the child window form button mouse move event is not getting displayed into the parent window form status bar label, please help
One of the good ways to do it is to use events in your child class:
First, declare the event:
public partial class ChildForm: Form
{
public event EventHandler ButtonClicked;
public ChildForm()
{
InitializeComponent();
}
}
Then call it in the button onClick method of the child form:
...
ButtonClicked?.Invoke();
...
if your onclick event is button_onclick then it would look like:
private void button_onclick(object sender, EventArgs e)
{
ButtonClicked?.Invoke();
}
and add your refresh login to this event when you declare this child form from your parent form:
var childForm = new ChildForm();
childForm.ButtonClicked += (e,args)=>{
//put the logic here
}
childForm.Show();
You could use a reference like this:
public partial class MainForm : Form
{
YourChildForm ycf = new YourChildForm(this);
ycf.Show();
}
And in your child form:
public partial class YourChildForm : Form
{
MainForm mf_ref
public YourChildForm(MainForm mf)
{
InitializeComponent();
mf_ref = mf;
}
}
Now you can access to every pubblic method on your mainform just using
mf_ref.SomeMethod();
How to come back to parent form without creating new instance of parent form in C# windows application?
I have tried this.Parent, this.MdiParent, this.MyParentForms but no one worked..
You can have a button in your parent form that is used to show another form. Add this code to the button's Click event:
//Click event of your button.
private void goToSecondForm_Click(object sender, EventArgs e)
{
this.Hide(); //Hides the parent form.
subform.ShowDialog(); //Shows the sub form.
this.Show(); //Shows the parent form again, after closing the sub form.
}
In your child form, add a public property with type of your parent form :
public class ChildForm:From
{
public ParentForm parent;
//...
}
Then, in your click event of showing child form, do this :
private void goToSecondForm_Click(object sender, EventArgs e)
{
this.Hide();
ChildForm child = new ChildForm();
child.parent = this;
//other stuff
child.Show();
}
At the end, in the FormClosing event of the child form, doing this :
private void Child_FormClosing(object sender, FormClosingEventArgs e)
{
this.parent.Show();
}
With this solution, if your parent form changes or updates, then you have the latest instance.
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!
I am passing data between 2 windows forms in c#. Form1 is the main form, whose textbox will receive the text passed to it from form2_textbox & display it in its textbox (form1_textbox).
First, form1 opens, with an empty textbox and a button, on clicking on the form1_button, form2 opens.
In Form2, I entered a text in form2_textbox & then clicked the button (form2_button).ON click event of this button, it will send the text to form1's textbox & form1 will come in focus with its empty form1_textbox with a text received from form2.
I am using properties to implement this task.
FORM2.CS
public partial class Form2 : Form
{
//declare event in form 2
public event EventHandler SomeTextInSomeFormChanged;
public Form2()
{
InitializeComponent();
}
public string get_text_for_Form1
{
get { return form2_textBox1.Text; }
}
//On the button click event of form2, the text from form2 will be send to form1:
public void button1_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
f1.set_text_in_Form1 = get_text_for_Form1;
//if subscribers exists
if(SomeTextInSomeFormChanged != null)
{
SomeTextInSomeFormChanged(this, null);
}
}
}
FORM1.CS
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string set_text_in_Form1
{
set { form1_textBox1.Text = value; }
}
private void form1_button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
f2.SomeTextInSomeFormChanged +=new EventHandler(f2_SomeTextInSomeFormChanged);
}
//in form 1 subcribe to event
Form2 form2 = new Form2();
public void f2_SomeTextInSomeFormChanged(object sender, EventArgs e)
{
this.Focus();
}
}
Now, in this case I have to again SHOW the form1 in order to automatically get the text in its textbox from form2, but I want that as I click the button on form2, the text is sent from Form2 to Form1, & the form1 comes in focus, with its textbox containing the text received from Form2.
I know this is a (really) old question, but hell..
The "best" solution for this is to have a "data" class that will handle holding whatever you need to pass across:
class Session
{
public Session()
{
//Init Vars here
}
public string foo {get; set;}
}
Then have a background "controller" class that can handle calling, showing/hiding forms (etc..)
class Controller
{
private Session m_Session;
public Controller(Session session, Form firstform)
{
m_Session = session;
ShowForm(firstform);
}
private ShowForm(Form firstform)
{
/*Yes, I'm implying that you also keep a reference to "Session"
* within each form, on construction.*/
Form currentform = firstform(m_Session);
DialogResult currentresult = currentform.ShowDialog();
//....
//Logic+Loops that handle calling forms and their behaviours..
}
}
And obviously, in your form, you can have a very simple click listener that's like..
//...
m_Session.foo = textbox.Text;
this.DialogResult = DialogResult.OK;
this.Close();
//...
Then, when you have your magical amazing forms, they can pass things between each other using the session object. If you want to have concurrent access, you might want to set up a mutex or semaphore depending on your needs (which you can also store a reference to within Session). There's also no reason why you cannot have similar controller logic within a parent dialog to control its children (and don't forget, DialogResult is great for simple forms)
I've a dgv on my main form, there is a button that opens up another form to insert some data into the datasource bounded to the dgv. I want when child form closes the dgv auto refresh. I tried to add this in child form closing event, but it doesn't refresh:
private void frmNew_FormClosing(object sender, FormClosingEventArgs e)
{
frmMain frmm = new frmMain();
frmm.itemCategoryBindingSource.EndEdit();
frmm.itemsTableAdapter.Fill(myDatabaseDataSet.Items);
frmm.dataGridView1.Refresh();
}
However, when I add this code in a button on the parent form, it actually does the trick:
this.itemCategoryBindingSource.EndEdit();
this.itemsTableAdapter.Fill(myDatabaseDataSet.Items);
this.dataGridView1.Refresh();
There are many ways to do this, but the following is the simpliest and it will do what you want and get you started.
Create a public method on your main form.
Modified constructor of second form to take a main form.
Create an instance of the second form passing the main form object.
When closing second form, call the public method of the main form object.
Form1
public partial class Form1 : Form {
public Form1() {
//'add a label and a buttom to form
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
Form2 oForm = new Form2(this);
oForm.Show();
}
public void PerformRefresh() {
this.label1.Text = DateTime.Now.ToLongTimeString();
}
}
Form2
public class Form2 : Form {
Form1 _owner;
public Form2(Form1 owner) {
_owner = owner;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form2_FormClosing);
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e) {
_owner.PerformRefresh();
}
}
We can also proceed this way:
We have form_1 and form_2
In form_1, create a public method. Inside this public method we put our stuff;
In form_2 we create a global form variable;
Still in form_2, pass form_1 into form_2 through form_2 constructor;
Still in form_2, make your global variable(the one we created in step 2) receive the new form_1 instance we created in form_2 constructor;
Inside the closing_event method we call the method which contains our stuff.
The method with our stuff is the method that will fill our form1 list, dataGridView, comboBox or whatever we want.
Form_1:
public fillComboBox()//Step 1. This is the method with your stuff in Form1
{
foreach(var item in collection myInfo)
{myComboBox.Items.Add(item)}
}
Form_2:
Form1 instanceForm1;//Step 2
public Form2(Form1 theTransporter)//Step 3. This the Form2 contructor.
{
InitializeComponent();
instanceForm1 = theTransporter;//Step 4
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
instanceForm1.fillComboBox();//Step 5 we call the method to execute the task updating the form1
}
I hope it helps...
You're creating a new instance of the main form which isn't effecting the actual main form instance. What you need to do is, call the code on the main form itself, just like the code you say works on the button click:
private void frmNew_FormClosing(object sender, FormClosingEventArgs e)
{
this.itemCategoryBindingSource.EndEdit();
this.itemsTableAdapter.Fill(myDatabaseDataSet.Items);
this.dataGridView1.Refresh();
}
Great answer there! The other method would have been:
Check if the form you want to update is open.
Call the method to refresh your gridVieW.
**inside your refreshMethod() in form1 make sure you set the datasource to null **
if (System.Windows.Forms.Application.OpenForms["Form1"]!=null)
{
(System.Windows.Forms.Application.OpenForms["Form1"] as Form1).refreshGridView("");
}