I have a simple c# winform and I'm trying to add a string to it.
e.g.
checklistbox1.Items.Add("string");
the problem is that after I close the form and run the program again, my added string is deleted from the checklistbox and I have to enter it again.
When you close the form, the members associated with it are removed as well. If you want it to be saved, you need to use a method that well save the data for you, such as XML, txt doc, or even a database, depending on the lifespan of the information you want to keep.
If it is only needed while the program is running, you may look into having the information stored in a member in the mainform rather than only just the form with the checklistbox.
Add a public List property to your form.
Create a second ctor for your form and inside your second ctor code
write:
public YourForm(List<string>() strings)
{
foreach(var item in strings)
{
checklistbox1.Items.Add(item);
}
}
You don't have to unload the form when closing. Let the parent form - I assume this is launched from another form - do the unloading/disposing of all the child forms instead. The trick is to make it appear to the user that you're closing the form. Let's say the form containing the checklist is Form2, the function that loads Form2 from the parent form will look like this:
Form2 _form2 = null;
private void button1_Click(object sender, EventArgs e)
{
if (_form2 == null)
{
_form2 = new Form2();
}
_form2.Show();
}
And in the Form2, handle the Closing event like this:
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
}
And finally, in the parent form Closing event, you can dispose Form2
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (_form2 != null)
{
_form2.Dispose();
_form2 = null;
}
}
If you need to have the same set of values for all instances of Form2, then you can use Singleton pattern. That's another discussion :)
Related
In a c# I have two forms: Windows Form1 & Windows Form2.
When I click on a link label in Form1, the second form is shown. But when I close the second form, my first Windows form closes too.
my main form is:
namespace Windows_Forms_Basics
{
public partial class ShowLocationOnMapForm : Form
{
private string latitude;
private string longitute;
private GeoCoordinateWatcher watcher = new GeoCoordinateWatcher();
public ShowLocationOnMapForm()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
watcher = new GeoCoordinateWatcher();
// Catch the StatusChanged event.
watcher.StatusChanged += Watcher_StatusChanged;
// Start the watcher.
watcher.Start();
}
private void button_ShowOnMap_Click(object sender, EventArgs e)
{
textBox_Latitude.Text = latitude;
textBox_Longtitude.Text = longitute;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "<Pending>")]
private void Watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e) // Find GeoLocation of Device
{
try
{
if (e.Status == GeoPositionStatus.Ready)
{
// Display the latitude and longitude.
if (watcher.Position.Location.IsUnknown)
{
latitude = "0";
longitute = "0";
}
else
{
latitude = watcher.Position.Location.Latitude.ToString();
longitute = watcher.Position.Location.Longitude.ToString();
}
}
else
{
latitude = "0";
longitute = "0";
}
}
catch (Exception)
{
latitude = "0";
longitute = "0";
}
}
private void label1_Click(object sender, EventArgs e)
{
}
private HelpForm form2 = new HelpForm();
private void linkLabel_help_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
this.Hide();
form2.Show();
}
}
}
and my second form is:
namespace Windows_Forms_Basics
{
public partial class HelpForm : Form
{
public HelpForm()
{
InitializeComponent();
}
private void HelpForm_Load(object sender, EventArgs e)
{
}
private void button_BackToForm1_Click(object sender, EventArgs e)
{
ShowLocationOnMapForm form1 = new ShowLocationOnMapForm();
this.Hide();
form1.Show();
}
}
}
Do you have any idea how to tackle this problem?
I am guessing you may be “confusing” forms and one forms “ability” to access another form. Let’s start by taking a look at the bit of code in your initial question…
private HelpForm form2 = new HelpForm();
private void linkLabel_help_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
this.Hide();
form2.Show();
}
This code is called from (what appears to be) a Form named ShowLocationOnMapForm.
On this form is a LinkLabel named linkLabel_help and its LinkClicked event is wired up and is shown above.
In addition, there appears to be a “global” variable form2 that is a HelpForm object (first line in the code above), which is another form. It is unnecessary to create this “global” form variable in the ShowLocationOnMapForm. …. However, we will continue as it is not pertinent at this point.
When the user “clicks” the `LinkLabel’ the above method will fire.
On the first Line in the method…
this.Hide();
Is going to “hide” the current form ShowLocationOnMapForm … and “show” the second form (HelpForm) with the line…
form2.Show();
On the surface, this may appear correct, however, there is one problem that I am guessing you are missing. The problem is…
How are you going to “unhide” the first form ShowLocationOnMapForm?
The second form (HelpForm) is “shown”, however, it isn’t going to KNOW anything about the first form. In this situation the first form is basically LOST and you have no way of accessing it. Therefore when you attempt the line… form1.Show(); in the second form, the compiler is going to complain because its not going to know what form1 is. In this code, there is NO way to get back to the first form. It is not only hidden from the user, but from the second form’s perspective the “CODE” can’t see it either!
Your faulty solution is not only “creating” another form1 but it is also doing the same with the second form.
Given this, it appears clear, that if you want to keep access to the first form… then you are going to have to use a ShowDialog instead of Show OR pass the first form to the second form.
Since it is unclear “how” you want these forms to interact, I can only proffer two (2) ways that you can use to at least keep access to the first form.
1) Use ShowDialog instead of Show when displaying the second form. It may look like …
private void linkLabel_help_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
HelpForm form2 = new HelpForm();
this.Hide();
form2.ShowDialog();
this.Show();
}
In the code above, the ShowDialog is going to “STOP” code execution in the first form and will wait for the second form (form2) to close. When executed, the first form is hidden, then the second form is shown, however, unlike the Show command, the line this.Show(); will not be executed until the second form closes. I am guessing this may be what you are looking for.
2) Pass the first form to the second form giving the second form “access” to the first form.
This will require that the second form has a “constructor” that takes a ShowLocationOnMapForm object as a parameter. With this, the second form can create a “global” variable of type ShowLocationOnMapForm that “points” to the first form. The constructor may look like…
private ShowLocationOnMapForm parentForm;
public HelpForm(ShowLocationOnMapForm parent) {
InitializeComponent();
parentForm = parent;
}
In the first form, you would instantiate the second form with...
HelpForm form2 = new HelpForm(this);
With this approach, the second form will have total access to the first form. You could add the “back” button as you describe and simply execute the line…ParentForm.Show(); However, I recommend you also wire up the second forms FormClose event and show the first form, otherwise, if the user clicks the close button (top right) and doesn’t click the “back” button, then you will have LOST the first form again.
Without knowing “exactly” how you want these forms to interact it is difficult to proffer a complete solution.
There are also other ways to accomplish this, however these should work for most cases.
I hope this makes sense and helps.
I tried to solve this problem by placing a 'Back to Form1' button in Form2. Which works, and the solution is as follows:
on my Form1 I have:
private Form2 form2 = new HelpForm();
private void linkLabel_help_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
this.Hide();
form2.Show();
}
and on my second form I have:
private void button_BackToForm1_Click(object sender, EventArgs e)
{
HelpForm form1 = new HelpForm();
this.Hide();
form1.Show();
}
But the problem is if I click the close button (on top right of the window) instead of the GoBack button on the second form, Form1 & Form2 both close in the same time.
I'm making like a add contact form with two buttons, ADD CONTACT and EDIT CONTACT. When a user clicks add contact, it pops up another form where the user can add contact information.
I want to give them the option to edit that info by clicking the EDIT CONTACT button which should pop up the SAME form.
However its not letting me call the object of the form twice, saying that I cannot press the edit button after the add button.
How do I call a form object twice?
//instatiating an object of the form
FormContact contactForm = new FormContact();
public FormManager()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
//displaying it when the user clicks add button
contactForm.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
//trying to display it again but gives this exception
///System.ObjectDisposedException: 'Cannot access a disposed
///object.
///Object name: 'FormContact'.'
contactForm.Show();
}
Error:
///System.ObjectDisposedException: 'Cannot access a disposed
///object.
///Object name: 'FormContact'.'
The problem is you're closing the form after you've shown it.
You click the Show button
Your only instance of the form is shown
You close it with the X in the top corner
The runtime destroys the form (disposes it) after it is closed
You try to show it again but this this it's gone, trashed, doesn't exist any more, waiting to be garbage collected
Either make a new form each time you open it (to reduce code clutter, assign this same event handler to both button clicks, or copy paste it out twice if you want them to be coded differently eventually):
private void btnAddOrEdit_Click(object sender, EventArgs e)
{
new FormContact().Show();
}
Or intercept the FormClosing event of the FormContact form and cancel the closing, and perform a Hide() instead so that instead of being destroyed your form is made invisible. It will then still exist and can be Show()n the next time. To handle the event, open the FormContact designer, click anywhere in the form background, click lightning bolt in properties grid, double click the FormClosing entry:
private void FormClosing(object sender, FormClosingEventArgs e){
e.Cancel = true;
this.Hide();
}
Which method you choose depends how you want your program to behave:
If you make a new form each time, and you Show instead of ShowDialog your user could click Add twice and see two forms. Then could click Add 10 times and see 10 forms. Using ShowDialog means that the main window won't accept any more clicks until the FormContact is closed. You might or might not want this either
If you Hide (not close; hiding is different from closing) and Show the same form rather than making a new one then the user can click Add 10 times but they still only see one form
FormContact contactForm = new FormContact(); is a Member variable, it's scope is Private and is visible to the entire class.
After you first Show the form:
contactForm.Show();
The form is already showing. Therefore if you call Show again, it won't do anything as the instance of the form/class is already showing.
If you want to show two instances of the form, you will need to instantiate two instances eg:
private void btnAdd_Click(object sender, EventArgs e)
{
FormContact contactForm = new FormContact();
contactForm.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
FormContact contactForm = new FormContact();
contactForm.Show();
}
Or make two instances of it:
FormContact contactForm1 = new FormContact();
FormContact contactForm2 = new FormContact();
private void btnAdd_Click(object sender, EventArgs e)
{
contactForm1.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
contactForm2.Show();
}
Or add a argument in the parameter of the Constructor to indicate Add or Edit, eg:
public class FormContact
{
public FormContact(int id)
{
if (id > 0)
{
//Load contact for Editing
}
else
{
//Clear all fields for Adding
foreach(var ctrl in this.Controls)
{
if (ctrl Is TextBoxBase) ctrl.Text = string.Empty
//TODO other controls types... if (ctrl Is ....
}
}
}
}
Then you can call it passing a contactID to edit or 0 to add:
FormContact contactForm = new FormContact(contactID);
contactForm.Show();
I've got another answer, in both methods simply show your form modally:
contactForm.ShowModal();
I'm actually building a program at school in .net. This is the first time I'm using it and I've got a question.
I got a MdiParent form which has two MdiChildren : a config form, and an articles list form. When you fill the config form, the articles list should appear.
I'm actually using this method in the MdiParent :
private void MotherMdi_MdiChildActivate(object sender, System.EventArgs e)
{
...;
}
But I need to deal with multiple variables because this method is fired every time a mdichild is open or closed ...
Is there a way to call a specific method only when One MdiChild is closed ?
Thanks a lot.
Event FormClosing is raised every time a windows form is closed. You can handle that event and do processing that you need to do when a form is closing.
In the parent form:
private void ParentForm_Load(object sender, EventArgs e)
{
ChildForm childForm = new ChildForm();
childForm.childFormClosed += childForm_childFormClosed;
}
void childForm_childFormClosed(object sender, FormClosedEventArgs e)
{
// Handle processing here
}
In the child form:
public event EventHandler<FormClosingEventArgs> childFormClosed;
private void ChildForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (childFormClosed != null)
{
childFormClosed(sender, e);
}
}
You may want to use FormClosed if that is what you need.
You can also use your own inherited class if you want to pass more information than what FormClosingEventArgs would do.
I have a MDI form. Within this MDI there is multiple button to open new forms. Let buttons are btn1, btn2, btn3, btn4.... When I press btn1, form1 is load. when I press btn2, form2 is load... Now I press btn1, And form1 is loaded. If I press again btn1 then another form1 is open. Simultaneously let form1 is open, if I press btn2 form2 is open. But I want to open a form at a time. How I prevent this?
all the answers you got are good so i'm not going to repeat them, just give you an example of the member and method you can use to prevent that from happening:
private Form frm;
private void button1_Clicked(object sender, EventArgs e)
{
if (frm != null)
{
frm.Close();
frm.Dispose();
}
frm = new Form1();
frm.Show();
}
private void button2_Clicked(object sender, EventArgs e)
{
if (frm != null)
{
frm.Close();
frm.Dispose();
}
frm = new Form2();
frm.Show();
}
You can read up about mutual exclusion http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
It is a general solution to make sure you only have 1 thing (thread, process, form, whatever) of something at the same time. You can even use it inter application.
An example is shown here: http://www.dotnetperls.com/mutex
You can create multiple mutexes, one for each form. Or one for a set of forms, in what ever combination suits you.
Example Scenario:
Form1 creates a mutex with name X
Form2 is being loaded checks whether mutex X is created, if so it closes itself.
Of course you will need to make sure the mutex is Disposed / released when the creator (Form1 in this example) closes, to allow other forms to show.
You can use some flag for this purpose OK, like this:
bool formOpened;
private void buttons_Click(object sender, EventArgs e){
if(!formOpened){
//Show your form
//..............
formOpened = true;
}
}
//This is the FormClosed event handler used for all your child forms
private void formsClosed(object sender, FormClosedEventArgs e){
formOpened = false;
}
At least this is a simple solution which works.
In general case, you need a int variable to count the opened forms, like this:
int openedForms = 0;
//suppose we allow maximum 3 forms opened at a time.
private void buttons_Click(object sender, EventArgs e){
if(openedForms < 3){
//Show your form
//..............
openedForms++;
}
}
private void formsClosed(object sender, FormClosedEventArgs e){
openedForms--;
}
Does this mean while you have Form1 open, you want to still be able to open a Form2 and 3 and etc?
It you don't want that, you can use the form1Instance.SHowDialog() instead of Show()...
But that generally means you can't access the parent form while form1 is open...
But King King's anwser might be more useable to you.
I have two Forms, Form1(main form) and Form2. Form 1 displays images files, pdf conversion, etc. But If user want to view Zip files, Form2 is called displaying a preview of all the Zip files available on a listView. If user selects a particular Zip file on Form2, the file is unzipped and image files sent to Form2. But I dont know how to refresh Form2 from Form1. By the way all the images from Form2 are now present in the variable list in Form! to be displayed but the form did not update.
form2 code:
private void btn_read_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
f1.ReadArchives(Filepath); //this function creates the image files on Form1
this.Close(); //close form2
for (int index = Application.OpenForms.Count - 1; index >= 0; index--)
{
if (Application.OpenForms[index].Name == "Form1")
{
//Application.OpenForms[index].Close();//EFFECTIVE BUT CLOSES THE WHOLE APPLICATION
Application.OpenForms[index].Invalidate(); //no effect
Application.OpenForms[index].Refresh();//no effect
Application.OpenForms[index].Update();//no effect
Application.OpenForms[index].Show();//no effect
}
}
}
So when you want the parent form to do something when something happens on the child form the appropriate mechanism is to use events. In this case the child form is being closed right when we want the information passed, so we can just re-used the FormClosed event.
This makes writing the child form very simple:
public partial class Form2 : Form
{
public string Filepath {get;set;}
private void btn_read_Click(object sender, EventArgs e)
{
Close();
}
}
The parent form can then use the appropriate event to handle the rest:
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs args)
{
Form2 child = new Form2();
child.FormClosing += (_, arg) => ReadArchives(child.Filepath);
child.Show();
}
private void ReadArchives(string filepath)
{
throw new NotImplementedException();
}
}
You are instantiating new Form1 in your code - which is different from Form1 (main) you already have. This is why form doesnt get updated.
In my answer I show event-based approach to share variables/objects between different forms - it can be easily adjusted to transmit collection of objects. Hope it helps.