Avoid duplicate form loading in c# - c#

I have 2 windows forms.Both Form1 and form2 have a button. When I click the button in form1 it shows form2 and vice versa. But it create a duplicate form when I click button on each time. How to avoid it. please tell me. My code is given below.
Form1:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
}
Form2:
private void button1_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
f1.Show();
}

just use this method common and pass parameter like 'this' when button click
public bool formIsExist(Form frmOpen)
{
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
if (frm.Name == frmOpen.Name)
{
return true;
}
}
return false;
}

The problem is that you are creating a new form each time you click the button.
To solve this problem You could make your form static.
static Form1 form = new Form1();
private void button1_Click(object sender, EventArgs e)
{
form.Show();
}

My solution, you can try
Form1
private void button1_Click(object sender, EventArgs e)
{
FormCollection fc = Application.OpenForms;
bool present = false;
foreach (Form frm in fc)
{
if (frm.Name == "Form2")
{
present = true;
}
}
if (!present)
{
Form2 f2 = new Form2();
f2.Show();
}
}
Form2
private void button1_Click(object sender, EventArgs e)
{
FormCollection fc = Application.OpenForms;
bool present = false;
foreach (Form frm in fc)
{
if (frm.Name == "Form1")
{
present = true;
}
}
if (!present)
{
Form1 f1 = new Form1();
f1.Show();
}
}

The easiest way is to determine whether the target form is already there and in that case, open it.
For example, in Form1 do this:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = null;
for (int i = 0; i < Application.OpenForms.Count; i++)
{
if (Application.OpenForms[i] is Form2)
{
f2 = Application.OpenForms[i];
break;
}
}
if (f2 == null)
f2 = new Form2();
f2.Show();
}
To make a common method for all forms, you could try this:
public static T GetForm<T>() where T : Form
{
for (int i = 0; i < Application.OpenForms.Count; i++)
{
if (Application.OpenForms[i] is T)
return (T)Application.OpenForms[i];
}
return null;
}
And call it like:
Form2 f2 = GetForm<Form2>();
if (f2 == null) f2 = new Form2();

#Mostafiz' answer is almost correct. It just misses the code to show the found present form. (Sorry, do not yet have 50 reputation to write this as a comment)
Try this code:
Form1:
private void button1_Click(object sender, EventArgs e)
{
Form form = null;
//search all opened forms for one with name "Form2"
foreach( Form frm in Application.OpenForms )
if( frm.Name == "Form2" ) //this requires Form2 to be named "Form2"
{
form = frm;
break;
}
//if no opened Form2 was found, create a new one
if( form == null )
form = new Form2();
form.Show();
}
Form2:
private void button1_Click(object sender, EventArgs e)
{
Form form = null;
//search all opened forms for one with name "Form1"
foreach( Form frm in Application.OpenForms )
if( frm.Name == "Form1" ) //this requires Form1 to be named "Form1"
{
form = frm;
break;
}
//if no opened Form1 was found, create a new one
if( form == null )
form = new Form1();
form.Show();
}

Related

Close childForm when Open a New childForm in MDI Parent?

I have a treeView to open each child Form, but when I open new child form I can still see the previous child form behind the new child form. What I want to do is close the old child form when open a new one. (childForm.Close(); // not working somehow)
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
string selectedNodeText = e.Node.Text;
Form1 myform1 = new Form1();
Form2 myform2 = new Form2();
if (selectedNodeText == "1")
{
myform1.MdiParent = this;
myform1.Parent = this.splitContainer1.Panel2;
myform1.Dock = DockStyle.Fill;
this.splitContainer1.Panel2.Controls.Add(myform1);
myform1.BringToFront();
myform1.Show();
}
if (selectedNodeText == "2")
{
myform2.MdiParent = this;
myform2.Parent = this.splitContainer1.Panel2;
myform2.Dock = DockStyle.Fill;
this.splitContainer1.Panel2.Controls.Add(myform2);
myform2.BringToFront();
myform2.Show();
}
}
Take a look at the MdiChildren property of your form object. There is a reference to all forms you attached to your MdiContainer.
Another way is to store the reference to your forms in the class itself and close the old one if you open another:
private Form1 myform1 = null;
private Form2 myform2 = null;
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) {
string selectedNodeText = e.Node.Text;
if (selectedNodeText == "1" && myform1 == null) {
myform1 = new Form1()
// ... some code ...
if (myform2 != null) {
myform2.Close();
myform2 = null;
}
}
if (selectedNodeText == "2" && myform2 == null) {
myform2 = new Form2()
// ... some code ...
if (myform1 != null) {
myform1.Close();
myform1 = null;
}
}
}

Change the Form Text from another Form

I have 2 Winforms (on Visual C#). On Form1 I have a button and when the user clicks it, I want the text of Form2 to change,before I open Form2 (The text that appears on the top left cornet of my Winform).
I tried these (1) (2) but they don't work.
On Form2 I have
public string formtext
{
get {return this.Text;}
set {this.Text = value;}
}
This is my button on Form1
public void kryptonButton2_Click(object sender, EventArgs e)
{
// Form2
Form2 form2 = new Form2();
form2.Text = "Η πόλη του Πειραιά";
}
Note that I click that button to change the text and then I click on another button to open Form2.
Form2 opens, but the text isn't changed.
Your Form2 instance has to be accessible from your text changing routine.
private Form2 m_form2;
public Form1() {
InitializeComponent();
m_form2 = null;
}
Now that you have the ground work laid, you will need to call your m_form2 object using Show() and NOT ShowDialog():
private void ShowForm2(string optionalText) {
if (m_form2 == null) {
m_form2 = new Form2();
m_form2.Show();
} else {
m_form2.Focus();
}
if (!String.IsNullOrEmpty(optionalText)) {
m_form2.Text = optionalText;
}
}
With this setup, your button should work for Form2 by modifying your routine to do this:
public void kryptonButton2_Click(object sender, EventArgs e) {
ShowForm2(null);
m_form2.Text = "Η πόλη του Πειραιά";
}
OR using the optionalText parameter:
public void kryptonButton2_Click(object sender, EventArgs e) {
ShowForm2("Η πόλη του Πειραιά");
}
You could also do this using delegates. This is a very powerful feature of C#. If you would like to see a code example of that, look at my answer to this question here:
https://stackoverflow.com/a/19146929/153923
UPDATE
It sounds like you may only need an updated version of Mike Cheel's answer.
Try:
public void kryptonButton2_Click(object sender, EventArgs e) {
Form2 form2 = new Form2();
form2.formtext = "Η πόλη του Πειραιά";
form2.Show(); // Mike left this part out
}
Try:
public void kryptonButton2_Click(object sender, EventArgs e)
{
// Form2
Form2 form2 = new Form2();
form2.formtext = "Η πόλη του Πειραιά";
}
There are a couple of reasons why your approach doesn't work.
public void kryptonButton2_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2(); //<-- this is a new instance for Form2
form2.Text = "Η πόλη του Πειραιά"; //<-- and this is not your propery
//(as pointed out by #MikeCheel)
}
If you have no instance of Form2 then you could try and get it from Application.OpenForms but that is a HACK.
var frm2 = Application.OpenForms.Cast<Form>()
.FirstOrDefault(c => c.Name == "Form2");
if(frm2 != null)
form2.formtext= "Η πόλη του Πειραιά";
When you click the other button to open the form you need to hold onto the reference to it, so that your other button click event can use it:
private Form2 child;
public void openOtherForm_Click(object sender, EventArgs e)
{
child = new Form2();
child.Show();
}
Now you can use that field to manipulate it:
public void kryptonButton2_Click(object sender, EventArgs e)
{
form2.formtext = "Η πόλη του Πειραιά";
}

How can I ensure only a single instance of a Form will be opened?

On button click, I open a new form (lets say Form2), but I don't want that Form2 to open more than 1time. And I don't want to use .ShowDialog(), because it wont allow me to go to the Previous Form. How can I do that ?
You can use Application.OpenForms property to check if form already opened:
if (!Application.OpenForms.OfType<Form2>().Any())
{
Form2 form2 = new Form2();
form2.Show();
}
You can show existing form instead of creating new:
Form2 _form2 = null;
void Button1_Click(object sender, EventArgs e)
{
if (_form2 == null)
{
_form2 = new Form2();
_form2.Closed += Form2_Closed;
}
_form2.Show();
_form2.BringToFront();
}
private void Form2_Closed(object sender, System.EventArgs e)
{
_form2 = null;
}
You can issue the Show method, which will show the form and allow the users to get back to the form, but then you can also override the OnClosing event of the form:
protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
}
and that will keep the users from being able to literally close the form. Finally, if you wanted, you could Hide the form when the user closes it:
protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
}
and then you'll need to hold on to that instance in the first form so that you can re-show it when the button is clicked. So in the first form you might have a class field like this:
private Form2 _form2 = new Form2();
and then in the button click it would look like this:
_form2.Show();
and since they can't actually close the form this will always work.
You can try something like
bool windowIsNotOpen;
Mutex mutext = new Mutex(true, "Form2", out windowIsNotOpen);
if (!windowIsNotOpen)
{
// Form2 is already open
return;
}
You can do a static property that tells you whether it's open or not. You'd set it when the form is opened, and turn it off when the form is closed.
class Form2 {
public static bool IsOpen { get;set; }
public Form2() {
Load += (sender, e) => { Form2.IsOpen = true; };
Closed += (sender, e) => { Form2.IsOpen = false; };
}
}
Whenever you want to open it, check the flag first.
Form2 f;
bool isOpen = false;
private void button1_Click(object sender, EventArgs e)
{
if (f == null)
{
f = new Form2(); ;
f.FormClosed += new FormClosedEventHandler(f_FormClosed);
}
if (!isOpen)
{
isOpen = true;
f.Show();
}
}
void f_FormClosed(object sender, FormClosedEventArgs e)
{
isOpen = false;
}
Try this or use Application.OpenForms and check which one opened

Single instance of all WinForm forms

I am developing a C# Windows Forms application. I would like to have a single instance of all the forms.
So, when the user clicks on the Contact button, for instance, twice, instead of having two contact forms, I would to bring the single instance contact form to the front.
How can I achieve this?
Check if the form exists in collection of open forms before creating and showing the form using Application.OpenForms
if (System.Windows.Forms.Application.OpenForms["Form1"] as Form1 != null)
MessageBox.Show("Form1 is opened");
else
MessageBox.Show("Form1 is not opened");
public static Form GetOpenedForm<T>() where T: Form {
foreach (Form openForm in Application.OpenForms) {
if (openForm.GetType() == typeof(T)) {
return openForm;
}
}
return null;
}
And in your code, where you create the ContactForm:
ContactForm form = (ContactForm) GetOpenedForm<ContactForm>();
if (form == null) {
form = new ContactForm();
form.Show();
} else {
form.Select();
}
Simple as that:
Form fc = Application.OpenForms["Form1"];
if (fc != null)
{
fc.Focus();
}
else
{
Form1 f1 = new Form1();
f1.Show();
}
You can disable the contactButton when it is clicked and open the contactForm-
private void contactButton_Click(object sender, EventArgs e)
{
contactButton.Enabled=false;
//code to open the contactForm
}
When the contactForm is closed, you can re-enable the button-
contactButton.Enabled=true;
Try this combo
First make contact form a global object
private ContactForm contactForm;
Then your contact button handler:
private void contactButton_Click(object sender, EventArgs e)
{
if (contactForm == null)
{
contactForm = new ContactForm();
contactForm.FormClosing += new FormClosingEventHandler(contactForm_FormClosing);
}
contactForm.Show();
}
Then handle the FormClosing event of the ContactForm to hide it rather than close it:
private void contactForm_FormClosing(object sender, FormClosingEventArgs e)
{
contactForm.Hide();
e.Cancel = true;
}
Or if you want the contact form to close, and open as new next time, handle the FormClosed instead:
private void contactForm_FormClosed(object sender, FormClosedEventArgs e)
{
contactForm = null;
}
Then next time the button is clicked, the null if clause will be caught and the form will be set to a new instance and opened.
Form2 form2 = null;
private void button1_Click(object sender, EventArgs e)
{
bool isFormExists = false;
foreach (Form openForm in Application.OpenForms)
{
if (openForm == form2 && openForm!=null)
{
openForm.Focus();
isFormExists = true;
break;
}
}
if (!isFormExists)
{
form2 = new Form2();
form2.Show();
}
}
I'd go with Otiel's answer. Also you can add a WindowState, because if the form is minimized it won't be shown. this answer can be used to get the restore method.
ContactForm form = (ContactForm) GetOpenedForm<ContactForm>();
if (form == null) {
form = new ContactForm();
form.Show();
} else {
//use this (if you want it to be restored to normal and focused)
//no need of extension method
//form.WindowState = FormWindowState.Normal;
//form.Select();
//or use this if you want it to be restored as previous state and focused
//You need a Restore extension method that can be found in the link above
form.Focus();
form.Restore();
}

Creating a new form, switching focus between the new and the old form with a button

I have a form and I want to get an instance of the same form as stated in the code below. And I have a button: every time I press this button, if a new form is created, I want it to focus to that window, if not, I want to create a new form.
I managed to create a new form but if I want to focus on it, the code did not work, any ideas?
private void btn_Click(object sender, EventArgs e)
{
if (opened == false)
{
Text = "form1";
var form = new myformapp();
form.Show();
opened = true;
form.Text = "form2";
}
else
{
if (Application.OpenForms[1].Focused)
{
Application.OpenForms[0].BringToFront();
Application.OpenForms[0].Focus();
}
if (Application.OpenForms[0].Focused)
{
Application.OpenForms[1].BringToFront();
Application.OpenForms[1].Focus();
}
}
}
You can try shortening your code without the need to introduce more variables with this example:
void button1_Click(object sender, EventArgs e) {
bool found = false;
for (int i = 0; i < Application.OpenForms.Count; ++i) {
if (Application.OpenForms[i].GetType() == typeof(myformapp) &&
Application.OpenForms[i] != this) {
Application.OpenForms[i].Select();
found = true;
}
}
if (!found) {
myformapp form = new myformapp();
form.Show();
}
}
Updated code from Francesco Baruchelli's comment.
If I understand correctly what you are trying to do, you can keep a static List with the opened forms. Everytime an instance of your Form is opened you add it to the List, and everytime it is closed you remove it. The when you press the button you can check the size of the List. If it is 1 you create a new Form, open it and set the focus on it. If the size is already 2, you look in the List for the instance which is different from the one executing the click event. The code could be something like this:
private static List<Form1> openForms = new List<Form1>();
private void button1_Click(object sender, EventArgs e)
{
Form1 frm = null;
if (openForms.Count == 2)
{
foreach (Form1 aForm in openForms)
if (aForm != this)
{
frm = aForm;
break;
}
}
else
{
frm = new Form1();
frm.Show();
}
frm.Focus();
}
private void Form1_Load(object sender, EventArgs e)
{
openForms.Add(this);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
openForms.Remove(this);
}

Categories

Resources