Whenever I need to show another Form, I always instantiate a new Form Object to show another Form (then hiding the current form).
/*Code in Form1*/
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show();
this.Hide();
}
After I instantiated and showed the second Form, I want to dispose the previous form (to free up some memory usage) but it is not working on the main context form.
However, the Dispose() method is working on other WinForms which is
not the main context form.
/*Code in Form2*/
private void button1_Click(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
frm1.Show();
this.Dispose();
}
Is it possible to instantiate a Form Object once only, then eventually to call/show it whenever I need it?
You can start your own ApplicationContext, and pass that to every form you want to make the MainForm. You shouldn't keep forms in memory and open and close them at will in my opinion. This could lead to potential memory leaks.
ApplicationContext ac = new ApplicationContext();
ac.MainForm = new Form1(ac);
Application.Run(ac);
(You will put this in the place of Application.Run(new Form1());)
In Form1, when you want to make Form2 the main form:
ac.MainForm = new Form2(ac);
this.Close();
This way, the form can be disposed (since you called Close() and used Show it will automatically dispose) and memory can be cleared. The instance of Form2 will be the new main form.
/*Code in Form1*/
Form2 frm2; // --> Inside the class
private void button1_Click(object sender, EventArgs e)
{
if (frm2 == null)frm2 = new Form2();
frm2.Show();
this.Hide();
}
.
/*Code in Form2*/
Form1 frm1;
//Constructor
public Form2(Form1 frm)
{
frm1= frm;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
frm1.Show();
this.Hide();
}
I would create a class called "FormHandler"
this may have a method like
here some prototype code (not tested)
public static class FormHandler
{
private static readonly Dictionary<string,Form> Instances = new Dictionary<string,Form>();
public TForm CreateFrom<TForm>()
{
string typeName = typeof(TForm).FullName;
if(Instances.ContainsKey(typeName))
{
return Instances[typeName]
}
else
{
// Create Instace with Activator.CreateInstance,
// and bind the dispose event to remove the form from the collection
// on dispose . Also make sure that you unbind the dispose Event
[...]
}
}
Now the buttonClick would just call
FormHandler.CreateForm<Form2>().Show();
with seperating the code to a new class you can avoid copy and paste in all buttons
Related
I designed a form for login that named as form1, and have 2 more form form2,form3
form2 items showing in panel from form1
and what I want to do
when I click the button in panel ( the item from form2 ) want to show form2 and hide form1 but the code isnt working
private void button1_Click(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
Form3 frm3 = new Form3();
frm1.Hide();
frm3.Show();
};
form3 is opening but form1 isnt hiding
Its not hiding because you created a new instance for form1 which is already instantiated.
You must call the Hide() method on the same instance used to call the Show() method.
If you added this code inside form1 class ,then change it like this
private Form1 frm1
public Form2()
{
frm1 = new Form1()
}
private void button_show_form1_Click(object sender, EventArgs e)
{
frm1.Show();
};
private void button1_Click(object sender, EventArgs e)
{
Form3 frm3 = new Form3();
frm3.Show();
frm1.Hide();
};
You creating both forms in your codesnipped. Form1 is not the form you want to close, i think. frm1 is only another instance of Form1, but not the openend instance von Form1. You must have anywhere another instance of Form1. You must use the right referenz to the right instance.
It is important to know that WinForms create an instance of the startup form. In our case the startup form would be Form1. So, when you say
Form1 frm1 = new Form1();
You're actually creating a new (second) instance of Form1. This means that, in code, there are two different Form1's.
What we want to do is check with our application to get the instance of Form1 that already exists.
// This goes in Form2. It returns an instance of Form1, if it exists.
private Form getForm1()
{
// Application holds information about our application, such as which forms are currently open.
var formCollection = System.Windows.Forms.Application.OpenForms;
// Now we loop through the open forms in search of the form we want, Form1.
foreach (Form frm in formCollection)
{
if (frm.Name.Equals("Form1"))
{
return frm;
}
}
return null;
}
Now that we can get the existing instance of Form1 we can use it to make the form hidden.
private void button1_Click(object sender, EventArgs e)
{
var form1 = getForm1();
if (form1 != null) form1.Hide();
}
Something to know here is that when a form is hidden it is not closed. So, we need to make sure that Form1 becomes visible again. For example, we can set Form1 to be visible when Form2 closes.
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
// The question mark (?) checks to see if the result of
// getForm1() is null. Same thing that is happening in
// button1_click
getForm1()?.Show();
}
Complete Form2 Code
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var frm1 = getForm1();
var frm3 = new Form3();
if (frm1 != null) frm1.Hide();
frm3.Show();
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
// The question mark (?) checks to see if the result of getForm1() is null. Same thing that is happening in button1_click
getForm1()?.Show();
}
// This goes in Form2. It returns an instance of Form1, if it exists.
private Form getForm1()
{
// Application holds information about our application, such as which forms are currently open.
// Note that Open and Visible have different definitions.
var formCollection = System.Windows.Forms.Application.OpenForms;
// Now we loop through the open forms in search of the form we want, Form1.
foreach (Form frm in formCollection)
{
if (frm.Name.Equals("Form1"))
{
return frm;
}
}
return null;
}
}
How can I lock (and make it look faded) a parent form while the child form is active? I tried to make the child form topmost but that just made it always visible and I can still edit the parent form. I want to be unable to operate on the main form while the child form is running in VS2012, C#. This is the code I used to call the second form...
private void checkButton_Click(object sender, EventArgs e)
{
Form2 newForm = new Form2(this);
newForm.Show();
}
One very simple way is to use ShowDialog() instead of Show() on the child form. This will prevent any interaction with the main form. This is also a neat way of passing back results. There are many other ways, of course.
Example:
private void checkButton_Click(object sender, EventArgs e)
{
Form2 newForm = new Form2(this);
newForm.ShowDialog();
}
See MSDN for further details: https://msdn.microsoft.com/en-us/library/c7ykbedk(v=vs.110).aspx
Just add Hide() for Current Running Form,
private void checkButton_Click(object sender, EventArgs e)
{
Form2 newForm = new Form2(this);
this.Hide();//hide old form
newForm.Show();
}
You can use Form.ShowDialog to create dialog which will open on top of parent form and will not allow to edit parent until you close child
private void checkButton_Click(object sender, EventArgs e)
{
Form2 newForm = new Form2(this);
newForm.ShowDialog(this);
}
You might wanna run the form2 in separate thread and set topmost = true, the form1 will function unblocked, but the form2 will run whatever you want unblocked too. Is this what you want?
namespace TestModal
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread thrd = new Thread(newwindow);
thrd.IsBackground = true;
thrd.Start();
}
private void newwindow()
{
Form2 frm2 = new Form2();
frm2.TopMost = true;
frm2.ShowDialog();
}
}
}
I have a problem with calling method from another class. Form1.cs contains:
public void RefreshTreeview()
{
MessageBox.Show("test");
this.treeView1.Nodes.Clear();
this.textBox10.Text = "test";
}
When I'm trying to call this method from another class "Form2.cs":
public void button2_Click(object sender, EventArgs e)
{
Form1 Obj = new Form1();
Obj.RefreshTreeview();
this.Close();
}
I'm receiving only message box with text. Treeview doesn't "clear" and textBox10 didn't dipslay "test". However when i'm trying to call the same method from method inside Form1 all elements were executed:
private void toolStripButton1_Click(object sender, EventArgs e)
{
RefreshTreeview();
}
Of course both classes are public. Please help.
Regards
I would suggest to retrieve the same Form1 instance which is probably the one you are actually seeing on the screen.
public void button2_Click(object sender, EventArgs e)
{
Form1 Obj = // retrieve instead of create a new one
Obj.RefreshTreeview();
this.Close();
}
To retrieve the Form1 instance there are multiple ways please leave a comment if required.
If you want to create a new instance of the Form1 and then clear it you have to use Show() method. E.g.:
public void button2_Click(object sender, EventArgs e)
{
Form1 f = new Form1();
f.RefreshTreeview();
f.Show();
}
But I assume your aim is to clear already existing form. Easiest way is to inform the Form2 who is its owner. Then you can access the owner from the Form2.
So in the method you use to invoke Form2 from Form1, instead of using Show() method use Show(this) - this way you pass current instance as the owner of the new dialog.
Code in Form1, where you invoke Form2:
Form2 f2 = new Form2();
f2.Show(this); // Current window is now the owner of the Form2
And now on the Form2 you can do your thing with accessing Form1, removing Nodes and setting text:
private void button1_Click(object sender, EventArgs e)
{
if (this.Owner == null) return; // Sanity check if there is no owner.
Form1 f = (Form1)this.Owner; // Get the current instance of the owner.
f.RefreshTreeview();
f.Show();
}
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 this block of code:
Form1 newForm = new Form1();
newForm.Show();
//The rest of this code has been omitted
more or less. Form1 is just for example purposes. My issue is that I am creating a text editor (continuation of my last question, basically) and I want to be able to have more than one copy of Form1 open at once.
This code allows me to do that, which is great, but I want to be able to close the old one and still have the newForm on the screen. Currently, if I close Form1, I say goodbye to newForm.
Is this possible? I don't want to have to just white-out all the next like Notepad does.
I'm guessing your Form1 is also the one created and passed to Application.Run() in your main method, correct? Something like Application.Run(new Form1());
In that case (which is the default), you are telling the framework to exit the application when that form closes.
You probably want to change your main method to use the overload of Application.Run() that takes an ApplicationContext, and within the app context, create your forms - then when your last form closes, you can exit the application. The example in the link to MSDN shows a very similar case.
You could simply change main to:
Form1 newForm = new Form1();
newForm.Show();
Application.Run();
but the issue with this is that the application may not exit correctly without more housekeeping by you.
Added:
This is a simple example, but shows the concept. Create a ApplicationContext class like this one:
public class CustomContext : ApplicationContext
{
private readonly List<Form1> _openForms = new List<Form1>();
public CustomContext()
{
CreateForm();
}
private void CreateForm()
{
Form1 form = new Form1();
form.OpenNewForm += (sender, args) => CreateForm();
form.Closed += (sender, args) => FormClosed(sender as Form1);
_openForms.Add(form);
form.Show();
}
private void FormClosed(Form1 form)
{
_openForms.Remove(form);
if (_openForms.Count == 0)
{
ExitThread();
}
}
}
In your Program class, change main to Run(..) your new context class:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new CustomContext());
}
And then in your Form1, make sure you have an event, and trigger that event to open new forms (note that in "real" code I'd probably abstract this away, or most likely let my DI container handle registration, but this shows the point much clearer) :
public event EventHandler OpenNewForm;
private void ButtonClick(object sender, EventArgs e)
{
//instead of showing a new form, we just raise this event
if (OpenNewForm != null) OpenNewForm(this, EventArgs.Empty);
}
What this does, is let the ApplicationContext manage your open forms, so that closing the first one (or any of them) does not exit the application until you close the last one. Once the last form closes, it exits the app.
You could do this so many different ways. For a working example of what you want to do, in the Program.cs file change the Main method():
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
Form1 frm = new Form1();
GlobalVariables.FormsList = new List<Form1>(); //new
GlobalVariables.FormsList.Add(frm); //new
frm.Show();
Application.Run();
}
Then on each of your Form1's have a button (or other event) that instantiates a new instance of the form1:
private void button1_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
GlobalVariables.FormsList.Add(frm); //new
frm.Show();
}
Edit: Also add the following code to the FormClosing event:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (GlobalVariables.FormsList.Count == 1)
{
Application.Exit();
}
else
{
GlobalVariables.FormsList.RemoveAt(GlobalVariables.FormsList.Count - 1);
}
}
Edit: Here is the new GlobalVariables class with the list of Forms to aid form management:
public class GlobalVariables
{
public static List<Form1> FormsList { get; set; }
}
If you are closing the form using it's 'x' button it will not affect the other form.
If you are closing by code you should get the object of that form properly and close it. It would be better if you can keep a catalog of forms so that the management will be easy.
If there are any static variables involved in between try changing that logic without static variables as they are shared across the objects.
Depending on what exactly you want to do, you can have the form launched by Application.Run be a form that just launches other forms, (e.g. your text-editor form).
Something like: (This is just an example to demonstrate the idea.)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Shown += Form1_Shown;
}
void Form1_Shown(object sender, EventArgs e)
{
TextEditorForm frm2 = new TextEditorForm(this);
frm2.Show();
this.Hide();
}
}
And:
public partial class TextEditorForm : Form
{
Form1 frm1;
public TextEditorForm(Form1 frm1)
{
InitializeComponent();
this.frm1 = frm1;
}
private void button1_Click(object sender, EventArgs e)
{
frm1.Show();
this.Close();
}
}