How to call a function from another form - c#

this is probably one of the most common question out there, having a FORM1 and FORM2, how I can call a function (on FORM1) like: MySQLConnect from FORM2. I tried couple of options and I can't get it to work, in the second attempt I tried calling the function from a button, but no luck.
Form1.cs (My first attempt:)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Form2 form2 = new Form2(this);
}
public void MySQLConnect(object sender, EventArgs e)
{
// Starting a MySQL connection
}
}
Form2.cs (My first attempt:)
public partial class Form2 : Form
{
Form1 mainForm;
public Form2(Form1 mainForm)
{
InitializeComponent();
this.mainForm = mainForm;
// call function on form1 MySQLConnect()
mainForm.MySQLConnect();
}
}
Form1.cs (My Second attempt:)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void MySQLConnect(object sender, EventArgs e)
{
// Starting a MySQL connection
}
}
Form2.cs (My Second attempt:)
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void btnMySQLConnect(object sender, EventArgs e)
{
Form1 myForm1 = new Form1();
myForm1.MySQLConnect(sender, e);
}
}
Please help!

Your first example works if you pass the parameters expected by MySqlConnect.
public partial class Form2 : Form
{
Form1 mainForm;
public Form2(Form1 mainForm)
{
InitializeComponent();
this.mainForm = mainForm;
mainForm.MySQLConnect(this, new EventArgs());
}
}
However, I can't imagine what a function named MySqlConnect could do with the parameters passed.
So it is better to remove them in the method definition and do not pass anything when you call it.
And I agree with the comments above. Why do you hide such important (and often required functionality) inside a Form instance? You have to pass this form instance everywhere you need to connect to your database. It is better to prepare some static service class ( in a Database Access Layer) that carry on this job

mainForm.MySQLConnect();
public void MySQLConnect(object sender, EventArgs e)
Any ideas? You just omitted arguments.

Related

Calling method / refreshing data in another form

So I have 2 forms - frmMain and frmChild
The frmChild form is declared as I run frmMain
frmChild form1 = new frmChild();
I also have a button that runs a method to open the frmChild form.
OpenForm(form1);
The question is, how can I update data / call desired method on the frmChild form while I'm still on the frmMain form? I need to do it on the existing instance of the form, without creating a new one.
I've tried doing it this way, but can't access the method
The frmMain class
public partial class frmMain: DevExpress.XtraEditors.XtraForm
{
frmChild form1 = new frmChild();
private void UpdateDataOnChildForm()
{
form1.UpdateData(); // cant access this method...
}
}
The frmChild class
public partial class frmChild : DevExpress.XtraEditors.XtraForm
{
public void UpdateData()
{
//update data here...
}
}
any tips will be appreciated
public partial class frmMain : Form
{
private frmChild form1 = new frmChild();
private DoSomeActionOnfrmChild()
{
form1.SomeAction();
}
}
public partial class frmChild : Form
{
public void SomeAction()
{}
}
`public partial class MainForm : Form
{
private void btnMain_Click(object sender, EventArgs e)
{
LoginForm lfrm = new LoginForm;
LoginForm.ShowDialog();
}
private void SecureMethod(){//do sth};
}
public partial class LoginForm : Form
{
private void btnok_Click(object sender, EventArgs e)
{
SecureMethod(); //is not true
this.close(); //close loginform
}
}`

How to get access to parent form?

I have two Windows Form in project C#.
public partial class Form1 : Form
{
public void add(){
//
}
}
public partial class FormAdd : Form
{
//
}
In Form1 after button click I open FormAdd:
var form = new FormAdd();
form.Show();
After in FormAdd I try to call parent method add:
Form1 f = new Form1();
f.add();
But I can not get access to any methods and properties of parent form.
I get error:
One approach is to pass Form1 in as the Owner of your FormAdd instance in the Show() call:
public partial class Form1 : Form
{
private void button1_Click_1(object sender, EventArgs e)
{
var form = new FormAdd();
form.Show(this); // pass this instance of Form1 in as the Owner of our FormAdd instance
}
}
Now, over in FormAdd, cast the Owner property to Form1 and call add():
public partial class FormAdd : Form
{
private void button1_Click(object sender, EventArgs e)
{
if (this.Owner is Form1)
{
Form1 f1 = (Form1)this.Owner;
f1.add();
}
}
}
Based on your picture, try to add the code above one bracket. Since the error seems to be on the scope of your condition.
This should look like this:
else
position = 0;
//{ <-- Remove this and put it below
if (this.Owner is Form1)
{
//TODO:
}
} //This should be here
Everything should compile properly after that.

How to select 2 Form as parameters in a form in c#

I have a method in a class that take 2 parameters like this:
public static void ShowSelectedFeeds(Form1 frm, Form2 frm2)
{
//Some code here.
}
but I don't know how to recall it in a form,
I recall methods whit 1 parameters like this:
for example the Selectoin_method is in DbCon Class and take 1 parameter Form1 frm
in Form1_Load:
DbCon.Selection_method(this)
but when it's come to a method that take 2 parameters and I want to recall it in a Fome2_Load I use this code but it doesn't work(Shows NO exception or error, nothing happen at all)
private void AddFeedsbtn_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
DBConnection.ShowSelectedFeeds(frm, this);
}
what should I do?
The easiest way is to create aForm1 variable inside Form2 and set it in the constructor of Form2. Like:
public partial class Form2 : Form
{
Form1 form1;
public Form2(Form1 form)
{
InitializeComponent();
form1 = form;
}
}
So when you create a Form2 you should pass a Form1 instance in the constructor.
private void AddFeedbtn_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2(this);// <--- Form1 instance
frm2.StartPosition = FormStartPosition.CenterScreen;
frm2.ShowDialog();
}
And then you can pass the form1 variable in the method.
private void AddFeedsbtn_Click(object sender, EventArgs e)
{
DBConnection.ShowSelectedFeeds(form1, this);
}

How do I pass data from child of child form to parent form in C#?

I am new to c#. I have the following in my project in windows forms:
Form1 with button and DataGridView.
Form2 with button.
Form3 with button and 3 textBoxes.
As shown in the screenshot In form1, I click buttonOpenForm2 form2 pops up. Then in form2 I click buttonOpenForm3 form3 pops up which has 3 text boxes and button. Now the 3 forms are open.
I enter values in textBox1, textBox2 and textBox3 and when click buttonAddRow ( from form3) I want these values to be inserted into the DataGRidView in Form1.
My question is:
How can I add a row into DataGridView in Form1 ( parent) from form3 (child of child form) WITHOUT closing form2 and form3? I mean I want to pass the data while form2 and form3 are still open.
Please help me. Thank you
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonOpenForm2 _Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show();
}
}
Form2:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void buttonOpenForm3 _Click(object sender, EventArgs e)
{
Form3 frm3 = new Form3();
frm3.Show();
}
}
Form3:
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void buttonAddRow _Click(object sender, EventArgs e)
{
//What to write here to insert the 3 textboxes values into DataGridView?
}
}
You cannot expect to get complete code that's ready to be pasted. I quickly wrote this in notepad to give you idea about how events work best in such cases. I assumed Form1 directly opens Form3. Solution below shows how to use events.
You home work is to make it work by adding another form Form2 in between. You can do so by propagating same event via Form2 which sits in middle.
Form3.cs
public partial class Form3 : Form
{
public event EventHandler<AddRecordEventArgs> RecordAdded
public Form3()
{
InitializeComponent();
}
private void buttonAddRow _Click(object sender, EventArgs e)
{
OnRecordAdded();
}
private void OnRecordAdded() {
var handler = RecordAdded;
if(RecordAdded != null) {
RecordAdded.Invoke(this, new AddRecordEventArgs(txtQty.Text, txtDesc.Text, txtPrice.Text))
}
}
}
AddRecordEventArgs.cs
public class AddRecordEventArgs : EventArgs
{
public AddRecordEventArgs(string qty, string desc, string price) {
Quantity = qty;
Description = desc;
Price = price;
}
public int Quantity { get; private set; }
public string Description { get; private set; }
public decimal Price { get; private set; }
}
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonOpenForm3_Click(object sender, EventArgs e)
{
Form3 frm3 = new Form3();
frm3.RecordAdded += Form3_RecordAdded;
frm3.Show();
}
private void Form3_RecordAdded(object sender, AddRecordEventArgs e) {
// Access e.Quantity, e.Description and e.Price
// and add new row in grid using these values.
}
}
1 Solution
You can use pattern with sending data further by constructor (special setter before Show method) and getting them back after window is closed by public getter.
public partial class Form2 : Form
{
Data Data1 {get; set;}
//Instead of Data you can pass Form1 class as parametr.
//But this might lead to unreadable code, and using too mutch methods and fields that could be private, public
public Form2(Data data)
{
InitializeComponent();
Data1 = data;
}
private void buttonOpenForm3 _Click(object sender, EventArgs e)
{
//Repeat pattern
Form3 frm3 = new Form3(Data1);
frm3.Show();
}
}
Optionally you dont have to call 3rd window constuctor. Just create Instance of third window store it in first form and just Show it by calling first instance you passed with data. But this might be bad practice in larger scale.
2 Solution
You can use singleton pattern. Create Instance of an first form inside constructor of first form and use it in third form. But you would need to ensure that there will be no more then one and always one instance of this object in memory.
You can pass owner to method Show() for new forms. Then you can get owner form from Owner property.
private void buttonOpenForm2 _Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show(this);
}
So you can get Form1:
(Form1)frm2.Owner
and call public method of Form1 class and pass there your new data.

How to access a form control for another form?

I have two Form classes, one of which has a ListBox. I need a setter for the SelectedIndex property of the ListBox, which I want to call from the second Form.
At the moment I am doing the following:
Form 1
public int MyListBoxSelectedIndex
{
set { lsbMyList.SelectedIndex = value; }
}
Form 2
private ControlForm mainForm; // form 1
public AddNewObjForm()
{
InitializeComponent();
mainForm = new ControlForm();
}
public void SomeMethod()
{
mainForm.MyListBoxSelectedIndex = -1;
}
Is this the best way to do this?
Making them Singleton is not a completely bad idea, but personally I would not prefer to do it that way. I'd rather pass the reference of one to another form. Here's an example.
Form1 triggers Form2 to open. Form2 has overloaded constructor which takes calling form as argument and provides its reference to Form2 members. This solves the communication problem. For example I've exposed Label Property as public in Form1 which is modified in Form2.
With this approach you can do communication in different ways.
Download Link for Sample Project
//Your Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(this);
frm.Show();
}
public string LabelText
{
get { return Lbl.Text; }
set { Lbl.Text = value; }
}
}
//Your Form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private Form1 mainForm = null;
public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
this.mainForm.LabelText = txtMessage.Text;
}
}
(source: ruchitsurati.net)
(source: ruchitsurati.net)
Access the form's controls like this:
formname.controls[Index]
You can cast as appropriate control type, Example:
DataGridView dgv = (DataGridView) formname.Controls[Index];
I usually use the Singleton Design Pattern for something like this http://en.wikipedia.org/wiki/Singleton_pattern . I'll make the main form that the application is running under the singleton, and then create accessors to forms and controls I want to touch in other areas. The other forms can then either get a pointer to the control they want to modify, or the data in the main part of the application they wish to change.
Another approach is to setup events on the different forms for communicating, and use the main form as a hub of sorts to pass the event messages from one form to another within the application.
It's easy, first you can access the other form like this:
(let's say your other form is Form2)
//in Form 1
Form2 F2 = new Form2();
foreach (Control c in F2.Controls)
if(c.Name == "TextBox1")
c.Text = "hello from Form1";
That's it, you just write in TextBox1 in Form2 from Form1.
If ChildForm wants to access the ParentForm
Pass ParentForm instance to the ChildForm constructor.
public partial class ParentForm: Form
{
public ParentForm()
{
InitializeComponent();
}
public string ParentProperty{get;set;}
private void CreateChild()
{
var childForm = new ChildForm(this);
childForm.Show();
}
}
public partial class ChildForm : Form
{
private ParentForm parentForm;
public ChildForm(ParentForm parent)
{
InitializeComponent();
parentForm = parent;
parentForm.ParentProperty = "Value from Child";
}
}
There is one more way, in case you don't want to loop through "ALL" controls like Joe Dabones suggested.
Make a function in Form2 and call it from Form1.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public void SetIndex(int value)
{
lsbMyList.SelectedIndex = value;
}
}
public partial class Form1 : Form
{
public Form2 frm;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
frm=new Form2();
frm.Show();
}
private void button1_Click(object sender, EventArgs e)
{
frm.SetIndex(Int.Parse(textBox1.Text));
}
}
Here's also another example that does "Find and Highlight". There's a second form (a modal) that opens and contains a textbox to enter some text and then our program finds and highlights the searched text in the RichTextBox (in the calling form). In order to select the RichTextBox element in the calling form, we can use the .Controls.OfType<T>() method:
private void findHltBtn_Click(object sender, EventArgs e)
{
var StrBox = _callingForm.Controls.OfType<RichTextBox>().First(ctrl => ctrl.Name == "richTextBox1");
StrBox.SelectionBackColor = Color.White;
var SearchStr = findTxtBox.Text;
int SearchStrLoc = StrBox.Find(SearchStr);
StrBox.Select(SearchStrLoc, SearchStr.Length);
StrBox.SelectionBackColor = Color.Yellow;
}
Also in the same class (modal's form), to access the calling form use the technique mentioned in the #CuiousGeek's answer:
public partial class FindHltModalForm : Form
{
private Form2 _callingForm = null;
public FindHltModalForm()
{
InitializeComponent();
}
public FindHltModalForm(Form2 CallingForm)
{
_callingForm = CallingForm;
InitializeComponent();
}
//...

Categories