Accessing methods on open form from a parent form c# - c#

I want to access a method in a child form from parent form.I have used the following code to access the controls.
Form form = (Form)Application.OpenForms["frmname"];
if (tableform != null)
{
GroupBox grp = (GroupBox)tableform.Controls["grpbxname"];
Panel table = (Panel)grp.Controls["panelname"];
}
Using the following code I am able to access controls in the child form from the parent form.
Same way I want to access the function/method in the child form.
For ex: from.newmethod();
Is there any possibility to achieve this,without creating new instance of form.It windows application using c#.net
Thanks.

declaring a method public is not a good practice. you can create delegate or event instead. you can create public delegate for that method and execute that delegate from the outside the class Or you can create Event that you can handle from the outside of the class.
public partial class Form1 : Form
{
public delegate void dMyFunction(string param);
public dMyFunction delMyFunction;
public Form1()
{
InitializeComponent();
delMyFunction = new dMyFunction(this.MyFunction);
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.Show();
}
private void MyFunction(string param)
{
this.Text = param;
}
}
Now, you can call this delegate from the outside the class
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
Form1 frm = (Form1)Application.OpenForms["Form1"];
frm.delMyFunction.Invoke("Hello");
//On Form load this method will be invoked and Form1 title will be changed.
}
}

Related

Calling a button from form2 when clicking a button from form1

This is a demo example, I can't use the original code. This context is very simplified.
I want to call a button/event from the child form (form2) when I'm clicking a button from the mother form (form1). I want to do this via subscribing (which I don't really understard since I'm new to coding).
Mother form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.Show();
//Call the Button from Form2 here
}
}
Child Form:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("MessageBox called from Form1 or Form2");
}
}
What you want to do, the way you want to do it, is in general not a good idea as you should not be relying on UI controls on another from, from your other form.
What you can do to achieve what you asked for without rewriting anything is more like this:
1) in the button click of Form2, you do not do anything else than calling a method on Form2, event handler contains no other logic
2) you make that method of form2 public
3) from your button click on form1, you call that same public method of form2
again, this would work but it is not necessarily the best design, it really depends on the whole architecture of your app if this fits or not with the rest or there are better and different ways to accomplish this.
Don't call other form "button clicks", if you want to call some logic from different places, extract logic into dedicated class and call it from both places
public class MyLogic
{
public void Execute(string someParameter)
{
// Do something with parameter
}
}
Then use it in both forms
public partial class Form1 : Form
{
private readonly MyLogic _importantLogic;
public Form1()
{
InitializeComponent();
_importantLogic = new MyLogic();
}
private void button1_Click(object sender, EventArgs e)
{
_importantLogic.Execute(this.textBox1.Text);
}
}
public partial class Form2 : Form
{
private readonly MyLogic _importantLogic;
public Form2()
{
InitializeComponent();
_importantLogic = new MyLogic();
}
private void button1_Click(object sender, EventArgs e)
{
_importantLogic.Execute("Always Form 2");
}
}

How to access another class's method?

I have a WinForms application. In the main form, I coded a method that will clear all TextBoxes in whatever form is passed as a parameter. I want to call this method from another form. The following code is what I came up with after much trial/error and browsing this site. Is instantiating a new version of the main form every time the new form's clear all button is clicked good practice? If I were to make yet another form with it's own clear all button I would have to instantiate a new main form by similar practice (unless I made the method static)? Can anyone suggest alternative ways of accessing one form's method from a different form? Many thanks in advance.
Edit: I know making the method static would be a simple and effective solution, but I'm curious about using a non-static way.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void ClearAll(Form formToClear) //CLEAR TEXTBOXES
{
foreach (var box in formToClear.Controls.OfType<TextBox>())
{
box.Text = "";
}
}
}
public partial class NewItemForm : Form
{
public NewItemForm()
{
InitializeComponent();
}
private void clearAllButton_Click(object sender, EventArgs e)
{
Form1 mainForm=new Form1();
mainForm.ClearAll(this);
}
}
You don't have to make your ClearAll method static. It is enough if you keep a global reference to your main form. You can do it in Program.cs. This is not the best way though.
static class Program {
public static Form1 TheForm;
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
TheForm = new Form1();
Application.Run(TheForm);
}
}
Again! Just because it can be done, it does not mean that I would encourage you doing it. This is not in the spirit of OOP.
If the only reason you would like to access a Form1's method is to clear TextBoxes, then I would recommend creating an intermediate class:
public class InterForm : Form
{
public void ClearAll() //CLEAR TEXTBOXES
{
foreach (var box in this.Controls.OfType<TextBox>())
{
box.Text = "";
}
}
}
All other form should inherit from InterForm.
You should almost certainly create a static utility class with static functions. That will preserve memory by preventing unnecessary Form1 instances from being created. Depending on the size of your Form class and the objects/variables contained within, creating a new instance just to use 1 function from that class, could eventually result in a large amount of memory being lost over time. A static method in a static class would prevent that from happening because static methods are only defined/instantiated once in the lifetime of the process, versus once-per-instance.
You should probably go with something like:
internal static class FormUtils
{
internal static void ClearAllTextBoxes(Form form)
{
if (form == null)
return;
if (form.Controls.Count <= 0)
return;
foreach (var box in form.Controls.OfType<TextBox>())
{
box.Clear();
}
}
}
Then, that function would be used like this:
public partial class NewItemForm : Form
{
public NewItemForm()
{
InitializeComponent();
}
private void clearAllButton_Click(object sender, EventArgs e)
{
FormUtils.ClearAllTextBoxes(this);
}
}
You can use concept of Event here.
Your Another form form where you want to call method of your main form should be having a Event,
while creating an instance of this form (I guess you are creating an instance of this form from main form only) you can subscribe an event of this form to your targeted method.
So whenever you are required to call that method of your main form (from your another form), you can raise that event.
see below sample code.
Suppose Form1 is your main form
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void f2_ClearTextBoxOfForm(Form targetForm)
{
foreach (Control control in targetForm.Controls)
{
if (control is TextBox)
((TextBox)control).Text = string.Empty;
}
}
private void btnShowForm2_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.ClearTextBoxOfForm += f2_ClearTextBoxOfForm;
f2.Show();
}
}
and Form2 is your another form from which you want to clear all textboxes of Form1
public delegate void ClearTextBoxEventHandler (Form targetForm);
public partial class Form2 : Form
{
public event ClearTextBoxEventHandler ClearTextBoxOfForm;
public Form2()
{
InitializeComponent();
}
private void btnClearTextBox_Click(object sender, EventArgs e)
{
if (ClearTextBoxOfForm != null)
{
//here passing 'this' means we want to clear textBoxes of this form (Form2)
//you can pass any Form's object of which you want to clear Textboxes
ClearTextBoxOfForm(this);
}
}
}

Access Form1 control from Form2

In my application I have two forms (see image below). Clicking on "Add" button shows the second "Add wireless network" form.
After filling the form and clicking on "OK", second form adds the new profile and updates the wifi network profiles in the first form. There is a RefreshProfiles function in the first form and I call it in the second form with this:
((MainForm)this.Owner).RefreshWiFiProfiles();
and the "Add" button's code is this:
private void AddButton_Click(object sender, EventArgs e)
{
NewNetworkForm newNetworkForm = new NewNetworkForm();
newNetworkForm.Owner = this;
newNetworkForm.ShowDialog();
}
This setup is working fine, but since the number of lines increased as I added new things, I wanted to divide the code. So I created a class to contain some functions.
namespace WirelessNetworkManager
{
public class Tools
{
public static void RefreshWiFiProfiles(ListView ListViewControl)
{
// clear old list
ListViewControl.Items.Clear();
// update it
}
}
}
I call the method in the first form with this:
Tools.RefreshWiFiProfiles(ProfilesListView);
and it's working fine. The problem is, since I need to update the profiles list from the second form too, I need to call this in NewNetworkForm. I can access and pass the ProfilesListView in MainForm because it's in there. How can I pass a control that is in MainForm to a method in NewNetworkForm and modify it? Or is there a better approach to do this?
File structure
MainForm.cs (WirelessNetworkManager.MainForm)
NewNetworkForm.cs (WirelessNetworkManager.NewNetworkForm)
Tools.cs (WirelessNetworkManager.Tools)
You can set the Modifiers property of your ProfilesListView in Form2 to Public or Internal (It's Private by default) then you can access ProfilesListView of Form2 like this : Form2.ProfilesListView
For example:
ProfilesList.Refresh(Form2.ProfilesListView);
Your mistake is : You are creating a new Form when you are using RefreshWiFiProfiles() method.
You should access to existing Form2, for example if Form2 is Owner of Form1, this code works :
Form ownerForm = (Form)this.Owner;
Tools.RefreshWiFiProfiles(ownerForm.ProfilesListView);
Here is the complete example:
Form1 declaration:
Add a ListView to Form1, Set it's Modifiers to Public and add some items in it.
Add a Button to show Form2
Add a Button to clear Form2 ListView
Form1 Code:
public partial class Form1 : Form
{
Form2 form2;
public Form1()
{
InitializeComponent();
}
private void btnShowForm2_Click(object sender, EventArgs e)
{
form2 = new Form2();
form2.Owner = this;
form2.Show();
}
private void btnClearForm2List_Click(object sender, EventArgs e)
{
Tools.RefreshWiFiProfiles(form2.lstViewOfForm2);
}
}
Form2 declaration:
Add a ListView to Form2, Set it's Modifiers to Public and add some items in it.
Add a Button to clear Form1 ListView
Form2 Code:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void btnClearForm1List_Click(object sender, EventArgs e)
{
Form1 form1 = (Form1)this.Owner;
Tools.RefreshWiFiProfiles(form1.lstViewOfForm1);
}
}
Declaration of Tools Class:
public static class Tools
{
public static void RefreshWiFiProfiles(ListView listView)
{
listView.Clear();
}
}
I tried implementing this. __curious_geek's answer and it worked fine.
MainForm.cs
namespace WirelessNetworkManager
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void AddButton_Click(object sender, EventArgs e)
{
// passing "this" (MainForm) to the second form
NewNetworkForm newNetworkForm = new NewNetworkForm(this);
newNetworkForm.ShowDialog();
}
}
}
NewNetworkForm.cs
namespace WirelessNetworkManager
{
public partial class NewNetworkForm : Form
{
public NewNetworkForm()
{
InitializeComponent();
}
// a local variable to reference the first form (MainForm)
private MainForm mainForm = null;
// a second overloaded constructor accepting a form
public NewNetworkForm(Form callingForm)
{
// mainForm now refers to the first form (MainForm)
mainForm = callingForm as MainForm;
InitializeComponent();
}
private void OKButton_Click(object sender, EventArgs e)
{
// create wifi profile with user input
// accessing the ListView using this.mainForm
Tools.RefreshWiFiProfiles(this.mainForm.ProfilesListView);
this.Close();
}
}
}
Tools.cs
namespace WirelessNetworkManager
{
public class Tools
{
public static void RefreshWiFiProfiles(ListView ListViewControl)
{
ListViewControl.Items.Clear();
// iterate through wifi profiles and populate ListViewControl
}
}
}
Also the control element's (ListViewControl) Modifiers should be set to Public or Internal. Otherwise you'll get an error.
'WirelessNetworkManager.MainForm.ProfilesListView' is inaccessible due to its protection level

How to call function from another form

In my project I have a Settings form and a Main form.
I'm trying to call the Main form's MasterReset function from the Setting form, but nothing happens.
The Master form's Masterreset function looks like this.
public void MasterReset()
{
DialogResult dialogResult = MessageBox.Show("Are you sure you want to perform master reset? All settings will be set to default.", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dialogResult == DialogResult.Yes)
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string phonebook_path = path + "\\Phonebook\\Contacts.xml";
XmlDocument xDoc = new XmlDocument();
xDoc.Load(phonebook_path);
XmlNode xNode = xDoc.SelectSingleNode("People");
xNode.InnerXml = "";
xDoc.Save(phonebook_path);
listView1.Clear();
people.Clear();
}
else if (dialogResult == DialogResult.No)
{
return;
}
}
And I'm accessing it from the Settings form like this
private void btn_MasterReset_Click(object sender, EventArgs e)
{
Main f1 = new Main();
f1.MasterReset();
}
Why am I not seeing any results?
Do you know what composition over inheritance is?
In the form where you have MasterReset you should do something like this:
Llet's suppose that in your second form you have something like this, and let's suppose your "mainform" will be called "MasterForm".
public partial class Form1 : Form
{
private MasterForm _masterForm;
public Form1(MasterForm masterForm )
{
InitializeComponent();
_masterForm = masterForm;
}
}
Here's the code in your masterForm Class:
private void button2_Click(object sender, EventArgs e)
{
Form1 form1 = new Form1(this);
}
Here's in your form1:
private void btn_MasterReset_Click(object sender, EventArgs e)
{
_masterForm.MasterReset();
}
Hope this helps!
This worked for me: In your Program class, declare a static instance of Main (The class, that is) called Form. Then, at the beginning of the Main method, use Form = new Main(); So now, when starting your app, use
Application.Run(Form);
public static Main Form;
static void Main() {
Form = new Main();
Application.Run(Form)
}
Now, calling a function from another form is simple.
Program.Form.MasterReset(); //Make sure MasterReset is a public void
namespace F1
{
// Method defined in this class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//This method I would like to call in other form
public void function()
{
MessageBox.Show("Invoked");
}
// opening the new form using button click
private void OpenNewForm_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.ShowDialog();
}
}
// This is second form
public partial class Form2: Form
{
public Form2()
{
InitializeComponent();
}
// on button click Form1 method will be called
private void button1_Click(object sender, EventArgs e)
{
var mainForm = Application.OpenForms.OfType<Form1>().Single();
mainForm.function();
}
}
}
There are multiple solutions possible. But the problem itself arise from the bad design. If you need something to be accessed by many, then why should it belong to someone? If, however, you want to inform something about anything, then use events.
Your mistake is what you are creating another instance of form1, thus MasterReset is operating with form, which is not even shown.
What you can do:
Make (as Ravshanjon suggest) a separate class to handle that MasterReset (and maybe something else). But also add to it an event. form1 and form2 can both subscribe to it and whenever either of them call MasterReset - both will react.
Create form dependency (as BRAHIM Kamel suggested): when you create form2, then pass to it form1 instance (as constructor parameter or by setting public property), to be able to call public non-static methods of form1.
As a quick, but relatively legimate solution, make this method static:
private static Form1 _instance;
public Form1()
{
InitializeComponents();
_instance = this;
}
public static void MasterReset()
{
// alot of code
_instance.listView1.Clear();
// alot of code
}
this way you can call MasterReset from any other form like this Form1.MasterReset(). Disadvantage of this method is what you can not have more than one instance of form2 (which is more likely anyway).
I understand your problem, you can declare your function as public static void(also listView1 and people should be static too). Then when you want to call to like this:
private void btn_MasterReset_Click(object sender, EventArgs e)
{
Main.MasterReset();
}

Switching between two Windows forms

I am working on a game that utilizes Windows Forms in C#. I want to be able to use the first form to call a second form. I have this working. Then I would like for the second form to send data back to the first form rather than creating a new instance of the first form. Can this be done? I know I need to have my properties set up so that I can set the variables from one form to the other. I am just not sure how to go about calling the first form without creating a new instance of it.
Is there a way that this can be done?
For example if I have Form A create an instance of Form B, can I have Form B do some work and send the data back to the original Form A without creating a new instance of Form A?
If you don't use the Data sent back Form A right away then you could use the Form_Closing event handler Form B and then a public property in Form B also.
In your Form A it could look like this:
public partial class FormA : Form
{
FormB frmB = new FormB(); // Instantiate FormB so that you could create an event handler in the constructor
public FormA()
{
InitializeComponent();
// Event Handler for Form Closing
frmB.FormClosing += new FormClosingEventHandler(frmB_FormClosing);
}
void frmB_FormClosing(object sender, FormClosingEventArgs e)
{
String fromFormB = frm2.FormBData; // Get Data from Form B when form is about to close
}
private void button1_Click(object sender, EventArgs e)
{
frmB.ShowDialog(); // Showing Form B
}
}
And in your Form B it could look like this:
private void button1_Click(object sender, EventArgs e)
{
// Let just say that the data is sent back once you click a button
FormBData = "Hello World!";
Close();
}
public String FormBData { get; set; }
It's hard to say without knowing your full requirements. But generally I go like this (Somewhat psuedo code).
Form2 dialogForm = new Form2();
if(dialogForm.ShowDialog() == DialogResult.OK)
{
this.PropertyOnForm1 = dialogForm.PropertyOnForm2
}
This ofcourse relies that your second form is a dialog. You will need to set the dialogresult buttons on Form2, and have a public property that will be accessed from Form1 once the dialog has been completed.
Let me know if this doesn't work and I'll write up a different answer.
Since you are creating Form2 in Form1, you can create a custom event in Form2 and subscribe to it in Form1 at the time that you create Form2, if you are returning information from Form2 when you are closing it then Edper's or MindingData's answers will work.
Here is a quick and dirty example using EventHandler<TEventArgs>
Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.myCustomEvent += frm2_myCustomEvent;
frm2.Show();
}
void frm2_myCustomEvent(object sender, string e)
{
this.Text = e;
}
}
Form2
public partial class Form2 : Form
{
public event EventHandler<string> myCustomEvent;
int count;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
count +=1;
myCustomEvent(sender, count.ToString());
}
}

Categories

Resources