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();
}
Related
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");
}
}
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);
}
}
}
I have a project, where a wizard form is called to make a project. On the end of the wizard I want to send a 'world' object back to a variable in the Main form. But If I give the main form with it through the constructor I can't access it's methods or properties. Am I doing something wrong?
here is my code:
main form
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
this.NewProject();
}
private void NewProject()
{
var myForm = new ProjectWizard(this);
myForm.Show();
}
Wizard form code:
public ProjectWizard(Form form)
{
InitializeComponent();
MainForm = form;
}
private void finishButton_Click(object sender, EventArgs e)
{
//World world = new World();
//MainForm.CurrentWorld = world;
}
Thanks in advance.
You just need to make CurrentWorld public or internal on the MainForm class. Honestly, you're doing everything else right!
UPDATE: also make sure that the MainForm private field declared in Form1 is of the type MainForm and not just Form. So, change the constructor a tidge too:
public ProjectWizard(MainForm form)
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());
}
}
I have 2 Forms. Form1 creates Form2 like this:
public partial class Form1 : Form
{
private void button3_Click(object sender, EventArgs e)
{
Form2 AcqForm = new Form2();
AcqForm.Show();
string[] ret = AcqForm.fulldate;
MessageBox.Show(ret[27]);
}
}
public partial class Form2 : Form
{
public string[] fulldate; //Created in form 2
close(); //Need to get this string back on or before close event
}
How should I go about doing this?
You need to handle the Form2 instance's FormClosed event in the first form and access the public properties.
Using this snippet, you can get a little knowledge on it.
in Form1:
using(Form2 form2 = new Form2())
{
if(form2.ShowDialog() == DialogResult.OK)
{
MessagBox.Show(form2.fulldate);
}
}
In Form2:
public partial class Form2 : Form
{
public string[] fulldate {get; set;} // Create a Property
void CloseForm()
{
fulldate = "valueToReturn";
DialogResult = DialogResult.OK;
}
}
Assuming you want button3_Click to wait until AcqForm is closed before accessing fulldate, you'll first have to change AcqForm.Show(); to AcqForm. ShowDialog();. (Show() doesn't wait for it to close.)
As for the fulldate field – it will be accessible even after the form closes because the form still exist. SLaks' remark about it being a 'field' means that we have different names for different types of 'variables'. What you have declared in the class (without get and set) is called a field. A variable in a method is called a 'variable'.
If you still want to do something when AcqForm closes, do this:
In Form1's constructor, before the AcqForm. ShowDialog();:
AcqForm.FormClosing += AcqForm_FormClosing;
And in Form1's class:
void AcqForm_FormClosing(object sender, FormClosingEventArgs e)
{
//Whatever will be here will be done when the form is closing.
//Use 'FormClosed' for doing things AFTER the form has closed.
}