This question already has answers here:
Communicate between two windows forms in C#
(12 answers)
Closed 3 years ago.
First off I know there have been similar Q&A for this. I haven't seem to have found the answer I am looking for, but it's possible I missed it. Second I am new to the C# language as I've mostly worked in C++ so please forgive me if this is a stupid question.
A little background now on what I am trying to accomplish. I'm in the process of making a Paint application. The first form, Form1 as I'll call it is where all of the UI is for my application and where the user will draw. I want to allow the user to select different brush types and sizes. On Form1 I have a button which the user will click to change these options. When this button is clicked it will initiate what I'll call Form2. Form2 will have the options for brush type and size and when the user selects them and hits the OK button the size and brush type should be passed back. I am just using two int variables to hold the brush type and the brush size to keep things simple since Form1 needs to know this, not Form2.
All of the information I have found is for passing information from Form1 to Form2, when I really want to pass information from Form2 to Form1. Is there a simple way to do this? I will be passing information like this for several other buttons as well so I am hoping not to over complicate things.
Thank you very much for your time!!! :)
This is in Form1 which calls Form2
private void brushBtn_Click(object sender, EventArgs e)
{
//New form which will ask which brush type and the size
Form2 paintInfo = new Form2() ;
paintInfo.ShowDialog();
}
This is Form2
public partial class Form2: Form
{
public Form2()
{
InitializeComponent();
}
int typeOfBrush;
//User picked the circle brush
private void circleBrushBtn_Click(object sender, EventArgs e)
{
typeOfBrush = 1 ;
}
//User picked the square brush
private void squareBrushBtn_Click(object sender, EventArgs e)
{
typeOfBrush = 2 ;
}
private void okBtn_Click(object sender, EventArgs e)
{
//PASS THE BRUSH TYPE & SIZE BACK TO FORM1 WHEN USER HITS OK BUTTON
this.Close() ;
}
}
Usually this kind of program has a tool palette that contains the various tools.
The palette is non modal, meaning that you don't block the execution of code in the first form when you show the palette. It stays in some corner and you click over the icons in the palette to change your behavior.
But, if this is the case, then passing back information to form1 requires a delegate and an event handler
So, inside Form2 code you have
public enum ToolEnum
{
Draw = 1,
Rubber = 2,
Fill = 3,
......
}
public class Form2
{
public delegate void OnToolChanged(ToolEnum newTool);
public event OnToolChanged ToolChanged;
....
protected override palette_Click(object sender, EventArgs e)
{
// Code that retrieves the tool clicked....
ToolEnum choosenTool = GetTool();
// If someone is interested to know when the user changes tool
// then it has subscribed to the ToolChanged event passing an
// appropriate event handler
if(ToolChanged != null)
ToolChanged(choosenTool);
}
}
The form1 call the form2 in this way
// Open the form with the palette passing reference to this instance of form1.
// Important to link the two forms together....
Form2 f = new Form2(this);
// Now inform the form2 instance that this instance of form1
// wants to know when the user clicks another tool
f.ToolChanged += myToolChangedHandler;
....
// We receive here the notification of the click event on the palette form
public void myToolChangedHandler(ToolEnum newTool)
{
if(newTool == ToolEnum.Fill)
{
... adapt for the fill operation ...
}
}
EDIT
However, if you want the follow the simpler road of showing modally your Form2, then the code is easy
private void brushBtn_Click(object sender, EventArgs e)
{
//New form which will ask which brush type and the size
using(Form2 paintInfo = new Form2())
{
paintInfo.ShowDialog();
int brushType = paintInfo.BrushType;
}
}
....
public partial class Form2: Form
{
public Form2()
{
InitializeComponent();
}
int typeOfBrush;
public int BrushType
{
get {return typeOfBrush;}
set {typeOfBrush = value;}
}
private void circleBrushBtn_Click(object sender, EventArgs e)
{
this.BrushType = 1 ;
}
}
Don't overthink this. A form is just an object. From within Form1 you will create a new object of type Form2. Form2 can have whatever properties (two ints in your case) that can be set however you wish. Assuming you are using WinForms, you will probably want to show Form2 via ShowDialog() which is a blocking call. When ShowDialog() returns, you can then interrogate Form2 (you still have a handle to the object in Form1) about any of its properties.
If this is not enough to get you started, I'm sure someone else will post an entire coded solution.
Related
This question already has answers here:
Passing Values from one Form to another Form in a Button click
(4 answers)
Closed 2 years ago.
Okay, I saw a couple of answers to similar questions but nothing was quite right, so I thought I would write down my own problem. I have a couple of Forms that are supposed to be connected.
private void btnAdd_Click(object sender, EventArgs e)
{
AuthorForm authorForm = new AuthorForm();
authorForm.Show();
}
This is the code from the Form2 that opens once I want to create a new list of Authors. With that, the third Form "AuthorForm" pops up and that's where I want to enter a name to add to a listBox that is in Form2. I don't know how to pass the string from the TextBox to the other form.
I'm sorry if this doesn't make much sense. I'm pretty bad at trying to explain what I need but if you have questions, I'll try to explain better.
Hi and welcome to StackOverflow. There are several ways to achieve this but I believe the easiest would be to use a property in your AuthorForm as follows:
// Inside AuthorForm create the following...
public string AuthorName { get; private set; }
Having done that, you can set this property either in text changed, or when the user clicks to commit the entered text, you then read this property from the Form2.
// This goes inside the text changed off your name text box.
this.AuthorName = AuthorTextBox.Text; // Assuming the name of the textox is AuthorTextBox
Inside Form2 you call read the property as follows.
private void btnAdd_Click(object sender, EventArgs e)
{
AuthorForm authorForm = new AuthorForm();
authorForm.ShowDialog();
// Read the entered text from the property
var userInput = authorForm.AuthorName;
}
You can proceed to make use of the text the user entered after this.
If i'm not mistaken you want to change Form2 instance after authorForm.Show(); statment
You can initial public variable for example name in Form2 and then send all the form2 instance to AuthorForm with constructor (use this keyword) , now you can change variable from form2 in authorForm
see :
AuthorForm authorForm = new AuthorForm();
authorForm.Show(this);
AuthorForm :
Form2 form2;
public AuthorForm(Form2 form2)
{
this.form2 = form2;
}
public void DoSomething()
{
form2.name = "test";
}
If I got it right, you want to get values from from AuthorForm.
You can do that by adding a property to the AuthorForm, like that:
public string AuthorName { get; set; }
And use authorForm.ShowDialog() so all the opened forms will freeze until you use the Close() method in the form you opened as a dialog. And then you can continue the form.
For example:
AuthorForm.cs:
public void BtnClose_Click(object sender, EventArgs e)
{
AuthorName = "rom_totach";
Close();
}
MainForm.cs:
public void BtnOpenAuthorForm(object sender, EventArgs e)
{
AuthorForm form = new AuthorForm();
form.ShowDialog();
MessageBox.Show(form.AuthorName);
}
I hope I helped!
This question already has answers here:
How to update textbox in form1 from form2?
(3 answers)
Closed 4 years ago.
So this is a bit different to what I've seen:
How to change text in a textbox on another form in Visual C#?
I have a form (Form1) that runs when my C# application runs. A button Form1 opens Form2. On Form2, I have another button to set the text of the textbox on Form1, to the same value as a textbox on Form2.
Using a similar approach to:
Form1 frm1 = new Form1();
frm1.TextBoxValue = "SomeValue";
Doesn't work as it opens a new form completely, but I want to change the form1 that is already open, can someone please assist?
You must store Textboxvalue on Form2 in some property like this:
public string ReturnValue {get;set;}
private void Form2_button2_Click(object sender, EventArgs e)
{
ReturnValue = txtInput.Text;
}
Or You can change the access modifier for the generated field in Form2.Designer.cs from private to public.
Change this
private System.Windows.Forms.TextBox txtInput;
by this
public System.Windows.Forms.TextBox txtInput;
Then in Form1 you can get Value of ReturnValue When end user close Form2
private void Form1_popupButton_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.ShowDialog();
// get ReturnValue from form2
string ReturnValue = frm.ReturnValue ;
//get txtInput value directly
ReturnValue = frm.txtInput.Text;
}
I would like to help you as good as I can but the information you provided is not that clear to me.
What you could do is when creating a new form use the constructor to pass the text
E.G.
Form1 frm1 = new Form1("some value or variable");
When you need tailored information please provide more code and a better explanation of your problem.
You could create a constructor for Form2 that takes in Form1 as a parent:
public partial class Form2 : Form
{
Form1 Parent { get; }
public Form2(Form1 parent)
{
Parent = parent;
Parent.TextBoxValue = "SomeValue";
}
}
However I don't think this is good practice. If your Form2 needs to be passing a result back to Form1, then you need to reverse your approach. Instead you should have a public property or method on Form2 that you can assign from inside Form1.
I'm trying to pass from MainForm to InfoForm and from InfoForm to MainForm multiple times but the error comes up:
Form that is already displayed modally cannot be displayed as a modal dialog box. Close the form before calling showDialog.
I looked up at the similar questions on Stack Overflow but I didn't find the answer that works in my case.
So, here is my code in MainForm:
public MainForm(InfoForm forwardForm) // constructor
{
InitializeComponent();
forwardForm.Visible = false;
}
private void GoBtn_Click(object sender, EventArgs e)
{
InfoForm nextForm = new InfoForm(this);
nextForm.StartPosition = FormStartPosition.CenterParent;
nextForm.ShowDialog(this);
}
And, here is my code in InfoForm:
public InfoForm(MainForm prevForm) // constructor
{
InitializeComponent();
previous = prevForm;
prevForm.Visible = false;
}
private void BackBtn_Click(object sender, EventArgs e)
{
MainForm backForm = new MainForm(this);
backForm = previous;
backForm.ShowDialog();
}
I need to use showDialog(), because I want the next form to show in the center of the previous form. If I use just show(), then my problem is solved, but then I can't show the next form in the center of the previous one.
EDIT:
private void BackBtn_Click(object sender, EventArgs e)
{
MainForm backForm = new MainForm(this);
backForm = previous;
backForm.Show(); // previous code - backForm.ShowDialog();
}
Can you explain me what happened? This way my problem is solved on one hand, but on the other hand what if I want to keep the content (of textboxes and checkboxes) of previous form?
The following line is completely pointless MainForm backForm = new MainForm(this); because it is immediately followed by this backForm = previous. Did you mean this instead previous = backForm? Therein lies the reason you will get the following exception (you are calling ShowDialog twice on the same instance of MainForm and never calling Close in between).
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.Windows.Forms.dll
Additional information: Form that is already displayed modally cannot
be displayed as a modal dialog box. Close the form before calling
showDialog.
In any case, I don't see why you would need to ever create multiple instances of MainForm but rather just hide/show the single instance as needed. Hiding/showing a single instance also solves the issue you mention in your update regarding loosing the form controls' states (checkboxes, etc). I made the assumption that you want to have one form visible on the screen at a time here, plus I had to fill in some missing things you don't show like the private field declarations and the fact that MainForm must have a parameterless constructor.
public partial class MainForm : Form
{
InfoForm forwardForm;
public MainForm() // constructor
{
InitializeComponent();
this.forwardForm = new InfoForm(this);
}
private void GoBtn_Click(object sender, EventArgs e)
{
this.Hide();
forwardForm.StartPosition = FormStartPosition.CenterParent;
forwardForm.ShowDialog(this);
}
}
public partial class InfoForm : Form
{
MainForm previous;
public InfoForm(MainForm prevForm) // constructor
{
InitializeComponent();
this.previous = prevForm;
}
private void BackBtn_Click(object sender, EventArgs e)
{
this.Hide();
previous.Show();
}
}
I have 2 windows forms; Form1.cs and Form2.cs.
Here are the code for Form1.cs in which will show the Form2.cs and Hide the the current Form1.cs
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
this.Hide();
}
Here are the code for Form2.cs in which will show the Form1.cs and Hide the the current Form2.cs
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
this.Hide();
}
I have monitored the memory usage of the application and I have noticed that the memory usage of the application is increasing every time I execute the code above.
You're creating new forms on each button click, so you hold many instances in memory after clicking the buttons multiple times.
You're probably looking for this.Close() instead of this.Hide(), as the former will close and dispose the current form while the latter will only hide it.
If you want to hide and re-show the forms, you need to keep a reference to the forms. There are a lot of considerations (should a form be instantiated only once, or each time it is requested? Should it be possible for multiple instances of the same form be opened? And so on) and possible patterns and (third-party) solutions (e.g. Application Controller, What is a proper way of building Winform apps with multiple “screens”).
One solution would be to simply create your own form registry where each form has a singleton:
public static class FormRegistry
{
private static Lazy<Form1> _form1 = new Lazy<Form1>(() => new Form1());
public static Form1 Form1
{
get
{
return _form1.Value;
}
}
private static Lazy<Form2> _form2 = new Lazy<Form2>(() => new Form2());
public static Form2 Form2
{
get
{
return _form2.Value;
}
}
}
Then anywhere in code, you can just do FormRegistry.Form1.Show(). Please note this code is a proof of concept with many issues and much room for improvement, but it's there to give you the general idea.
Methods opening forms :
form1 --> form2 --> form3
ChecklistBox on the form1 there. How to know the form3 That is active or not?
If the forms you are referencing are MDI child forms, you could use
Form activeChild = this.ActiveMdiChild;
else you could use the following code if not using MDI child forms.
Form currentForm = Form.ActiveForm;
I understand that you are asking if form 3 is opened. If that is incorrect, please enlighten me.
There are probably dozens of ways to do so, it all depends on what you want to do.
One simple way would be to leave a flag somewhere, say in your Program.cs file:
public static bool Form3IsOpen = false;
Then:
private void Form3_Load(sender object, EventArgs e)
{
Program.Form3IsOpen = true;
}
And:
private void Form3_Close(sender object, EventArgs e)
{
Program.Form3IsOpen = false;
}
Supplemental:
You can also keep a reference to your subform:
In form1.cs:
private Form2 FormChild;
//In the function that opens the Form2:
FormChild = new Form2();
FormChild.Show();
Form2 will have something similar to retain Form3. If one form can open several, just use an array or collection.
When i usually have many different forms and only one instance to be created, i put them in dictonary and check it if there is a form.
Something like this:
public static Dictonary<string, Form> act_forms_in_app = new Dictonary<string, Form>();
now in every forms creation i do it like this
Form1 frm = new Form1();
frm.Name = "Myformname"
//set its properties etc.
frm.Load => (s,ev) { act_forms_in_app.Add(frm.Name, frm);};
frm.Load += new EventHandler(frm_Load);
frm.Disposed => (s, ev) { act_forms_in_app.Remove(frm.Name)};
//your usual form load event handler
public void frm_Load(object sender, EventArguments e)
{
...
}
somewhere where you want to check
Form frm = //Your form object
if(act_forms_in_app.ContainsKey(frm.Name))
{
//Perform as required
}