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();
Related
I have three forms, the main, the second one and the last which is opened by the second one using ShowDialog().
If I minimize the last form, I go back to the first form, and in turn a button is activated to return to the last form. If I click this button, I can see the last form but I can't use it, I can only see it.
How can I get the control of this form?
Code of Minimize of the last form:
private void button_minimize_Click(object sender, EventArgs e)
{
this.Hide();
Principal fom = new Principal(true, this);
fom.ShowDialog();
}
Code of first form to open again the last form:
private void bt_galvCh_Click(object sender, EventArgs e)
{
formMinimizadoGalv.Activate();
formMinimizadoGalv.BringToFront();
formMinimizadoGalv.Focus();
formMinimizadoGalv.Show();
}
This is the last form, I can see it with this code but I can use the green button:
Picture of the last form
Using: C# Forms VS2015
What I'm trying to do:
On form1, I have a textbox (tbJobTitle) and a button (bChooseJobTitle -> form2) for a "Job Title" of an employee.
The textbox(enabled=false) displays the chosen Job Title of an employee.
The button bChooseJobTitle opens another form (form2) that has a datagrid and 2 buttons (Choose & Cancel)
using System.Threading;
...
Thread the1;
...
private void bChooseJobTitle_Click(object sender, EventArgs e)
{
the1 = new Thread(OpenNew_tblJobTitle);
the1.SetApartmentState(ApartmentState.STA);
the1.Start();
}
private void OpenNew_tblJobTitle(object obj)
{
Application.Run(new form2());
}
...
I initially set a global string MyVar.Employee_Choose_idJobTitle (default "" ) to store the choosen index primary key if the user selected content and click the Choose button. If the Cancel button is click the MyVar.Employee_Choose_idJobTitle will remain = "".
//... at form2 "Choose" button
private void bChoose_Click(object sender, EventArgs e)
{
MyVar.idJobTitle = dataGridView1.CurrentRow.Cells[0].Value.ToString();
this.Close();
}
private void bCancel_Click(object sender, EventArgs e)
{
this.Close();
}
When form2 is closed either by "Choose" button or "Cancel" button, the focus goes back to form1's bChooseJobTitle button.
How do I trigger this event?
...so that can test if the content of MyVar.idJobTitle is not null and add the proper value to my textbox.
I was looking for the button events like onFocus or activate but could not find any. Do I use form events instead to do this?
Quite simply, use event Form Activate if you like.
private void form1_Activated(object sender, EventArgs e)
{
if (MyVar.idJobTitle != "")
{
tbJobTitle.Text = Choose_idJobTitle;
MyVar.idJobTitle = "";
}
}
I'm making a WPF project based on an Access database.
The database has two tables:
tblMovies (MovieID: PK, Title, Director, Genre etc)
tblActors (ActorID: PK, MovieID: FK, Firstname, Lastname etc)
I have listbox where I can see all the movies, and if I click on one, it shows a new window with all the details about that movie: the title, director, genre, but also the actors.
In this window I have added a button to create a new actor. This opens a new window where you can enter the MovieID (FK) and the information about the actor.
When I click save changes, it works and the window closes, but my listboxActors needs to be manually refreshed (I have added a button for that) to see the new actor.
Is there a way to refresh my listboxActors after I click "save changes" in my other window?
I first did it by closing my first screen when clicking add new actor, and then if I saved it would reopen the screen, and it'd automatically be refreshed, but I don't want it that way.
My listboxActors:
listBoxActors.ItemsSource = mov.Actors;
Save button (in the other screen)
private void buttonSaveNewActor_Click(object sender, RoutedEventArgs e)
{
Actor act = new Actor();
act.MovieID = Convert.ToInt32(textBoxMovieID.Text);
act.FirstName = textBoxFirstName.Text;
act.LastName = textBoxLastName.Text;
act.Country = textBoxCountry.Text;
act.Born = Convert.ToDateTime(BornDate.SelectedDate);
act.Bio = textBoxBio.Text;
ActorRepository.AddActor(act);
MessageBox.Show("The actor: " + act.FirstName + " " + act.LastName + " has been created");
this.Hide();
}
The refresh button:
private void buttonRefresh_Click(object sender, RoutedEventArgs e)
{
listBoxActors.ItemsSource = null;
listBoxActors.ItemsSource = mov.Actors;
}
Thanks in advance!
Well, Thanks for the explanatory comment...! I have a suggestion for you, please let me know if this helps you to code your scenario:
So you have two forms WindowShowDetails Let it be the main-form and WindowAddActor be the child, the Their will be a button in the main form which opens the child form, and you are doing some tasks in the child and press the Save button, which will save those details and closes that form. And you wanted to refresh the List in the main form associated with this event. For this you can use delegates and events;For this you have to do a number of tasks, in the main-form as well as in the child, Let me show you how it can help you:
Define a delegate in the main form:
public delegate void RefreshList();
Define an event of that delegate type
public event RefreshList RefreshListEvent;
Define a method that will do the action(ie, Refreshing the grid)
private void RefreshListView()
{
// Code to refresh the grid
}
Now need to define a Delegate in the WindowAddActor
Public Delegate UpdateActor;
Now we have to code the button click that opens the WindowAddActor form Let the button be btnAddActor so its Click event will be btnAddActor_click, we have to initialize our delegate-event, the instance of the WindowAddActor and assign the event to Delegate in the WindowAddActor before showing that form. this can be coded as :
private void btnAddActor_click(object sender, EventArgs e)
{
WindowAddActor actorInstance = new WindowAddActor();
RefreshListEvent += new RefreshList(RefreshListView); // event initialization
actorInstance.UpdateActor = RefreshListEvent; // assigning event to the Delegate
actorInstance.Show();
}
Now we have to call the delegate from the SaveButton's click event that is
private void buttonSaveNewActor_Click(object sender, RoutedEventArgs e)
{
// Perform save operation
UpdateActor.DynamicInvoke(); this will call the `RefreshListView` method of mainWindow
this.Close();
}
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 :)
Being a very first user in Windows Form Development I want to ask a simple question ...
I created a form(MainWindow.cs) within the solution which opens at the time of running that solution.
Latter I created a second form(SecondWindow.cs) and created a event so that it can be called from the first window by clicking a button.When the second window loded up the first window(MainWindow.cs) will be disabled.
Now I want to enable the MainWindow.cs when the second window is closed.
How to do That...
A simple solution I already have is to hide the MainWindow.cs and latter on closing the second window make a new object of first window and show it.But it is not a good way i think because there is already a object created by .net framework for first window automatically, so why we should create a new object of Mainwindow.cs .
Code Of First Window ( MainWindow.cs ) :
private void priceControllToolStripMenuItem_Click(object sender, EventArgs e)
{
SecondWindow price = new SecondWindow();
this.Enabled = false;
price.Show();
}
Code Of Second Window ( On closing SecondWindow.cs )
private void price_controll_FormClosed(object sender, FormClosedEventArgs e)
{
// what will goes here to make the MainWindow.cs to enable state
}
Use price.ShowDialog() to show second form as modal dialog. Main form will be disabled until you close second form:
private void priceControllToolStripMenuItem_Click(object sender, EventArgs e)
{
using(SecondWindow price = new SecondWindow())
price.ShowDialog();
}
You can pass the main form as an owner to the second form
private void priceControllToolStripMenuItem_Click(object sender, EventArgs e)
{
SecondWindow price = new SecondWindow() { Owner = this };
this.Enabled = false;
price.Show();
}
Then you can reference it from the second form.
private void price_controll_FormClosed(object sender, FormClosedEventArgs e)
{
Owner.Enabled = true;
}