Form Closing Event visual studio c# - c#

Straight to the problem:
In my main form, i have a three buttons that open three different forms. I will show you how it is built.
MainForm (Here is three buttons, with the three different form names on them)
Theory -> Click this button to open TheoryForm
Tasks -> Click this button to open TasksForm
Compete -> Click this button to open CompeteForm
Inside my TasksForm is a button that is going to open the TheoryForm. Here is my code:
public partial class TasksForm : Form
{
public TasksForm()
{
InitializeComponent();
}
public void TheoryButton_Click(object sender, EventArgs e)
{
Form TheoryForm_Child = new TeoriForm();
TheoryForm_Child.Show();
}
//Add some code here so that when `TasksForm` closes, the `TheoryForm_Child` closes too.
}
And what I can't figure out is, when the TasksForm is closed, the TheoryForm is supposed to close as well, right now it doesn't.

Try declaring the variable to your TheoryForm outside of the TheoryButton.Click event handler and then use it in your TaskForm.FormClosing event handler to close it.
public partial class TasksForm : Form
{
private Form TheoryForm_Child;
public TasksForm()
{
InitializeComponent();
FormClosing += TaskForm_FormClosing;
}
public void TheoryButton_Click(object sender, EventArgs e)
{
TheoryForm_Child = new TeoriForm();
TheoryForm_Child.Show();
}
public void TaskForm_FormClosing(object sender, FormClosingEventArgs e)
{
if(TheoryForm_Child != null)
TheoryForm_Child.Close();
}
}

Just because TasksForm is creating TheoryForm does not mean that when TasksForm is closed, so will TheoryForm. Instead, you should close it explicitly like by handing the closed event in your TasksForm, like this.
public partial class TasksForm : Form
{
Form _TheoryFor_Child = new TheoryForm();
public TasksForm()
{
InitializeComponent();
Closed += TasksForm_Closed;
}
private void TasksForm_Closed(object sender, EventArgs e)
{
_TheoryFor_Child.Close();
}
private void TheoryButton_Click(object sender, EventArgs e)
{
_TheoryFor_Child.Show();
}
}

You need to connect parent and child form in some way.
For example in giving the child form the parent form as owner.
Simply call
TheoryForm_Child.Show(this);

There is a really simple solution. You should use the other version of Show method like this:
Form TheoryForm_Child = new TeoriForm();
TheoryForm_Child.Show(this);
That's all. Then your form will be owner of theory form. So it will automagically destroy Theory form after closing itself.
More reading here: https://msdn.microsoft.com/en-us/library/szcefbbd%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

Related

Cancel events from a legacy form

I have a main form that has buttons, the role of one of them in disabling all controls of the form in general.
I also have a child form that inherits the buttons and the actions of them, as I could prevent the events of the parent form at a certain point from running that is, temporarily remove the event, for example if the user has a text and does not fill it out and gives the button I do not want anything to be disabled
I think there is a way in c# that like the "eventname"=- I don't remember well
This is an example of my base or parent form, with a button that does actions
Parent Form
namespace WindowsFormsApp1
{
public partial class BaseMantenimiento1 : DevExpress.XtraEditors.XtraForm
{
public BaseMantenimiento1()
{
InitializeComponent();
}
private void BaseMantenimiento1_Load(object sender, EventArgs e)
{
Guardar.Enabled = false;
Cancelar.Enabled = false;
controles.habilitarcontroles(false, xtraTabControl1);
}
private void Nuevo_Click(object sender, EventArgs e)
{
Guardar.Enabled = true;
Cancelar.Enabled = true;
Editar.Enabled = false;
Buscar.Enabled = false;
Nuevo.Enabled = false;
controles.habilitarcontroles(true, xtraTabControl1);
}
This is my child form with its basic code
child form
public partial class Mantenimiento_Empresas : BaseMantenimiento1
{
public Mantenimiento_Empresas()
{
InitializeComponent();
}
What I wanted was that if in the child form I gave the button save, but they did not fill the textbox well, then the event that this inherits from its parent form is not executed, so I took the event and then below if everything is fine I trigger the event of the parent with
base.Save_Click(null, null);
I found what I was looking for, in the same space where the components are initialized I must place the following
public Mantenimineto_Bicicletas()
{
InitializeComponent();
Save.Click -= base.Save_Click;
}

Make the startup form visible again after hiding it

I am trying to create a two-form Windows Application in C#. For simplicity and to help me figure it out before using it elsewhere, I have essentially created a Windows form application with two forms: Form1 and Form2, Form1 showing on startup. At the click of a button, I can get Form1 to "disappear" and Form2:
private void button1_Click(object sender, EventArgs e)
{
Form2 x = new Form2();
x.Show();
this.Hide();
}
And this works great. However, when I want to return to Form1 (by making it visible again) and unload Form2, I am unsure how to proceed with coding Form2 to return the user to Form1 using a button click as well. I'm not sure what to refer to to make that form visible again, instead of having to create a new Form1 and loading it, thereby leaving my original startup form sitting in memory.
Any help you can provide would be awesome! Thanks in advance,
-Jan
As Alfie comment suggests, you need to control your instances of each form somehow.
I'd suggest a static class with two variables. When you start up you link the forms to these public properties in the static class.
something like this:
public static class App {
public static Form Form1;
public static Form Form2;
}
on startup or the click method, you'd say something like:
private void button1_Click(object sender, EventArgs e)
{
if (App.Form1 != null)
{
App.Form1 = new Form1();
}
App.Form1.Show();
App.Form2.Hide();
}
Do this:
private void button1_Click(object sender, EventArgs e)
{
Form2 x = new Form2();
this.Hide();
x.ShowModal();
this.Show();
}

Switching between two Windows forms

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());
}
}

How to pass the value from one form to another one?

I have a MainForm and AnotherForm. AnotherForm is accessed via MainForm's menuItem.
AnotherForm has listView. When user clicks on an item it I want to get the string element and pass it to MainForm's textbox, so the element shows there and AnotherForm is closed. So far AnotherForm closes but nothing shows in the textbox in MainForm. Any suggestions?
private void listView1_ItemActivate(object sender, EventArgs e)
{
string input = listView1.SelectedItem[0].ToString();
MainForm mainF = new MainForm(input);// called the constructor
this.Close(); //close this form and pass the input to MainForm
mainF.inputTextBox.Text = input;
mainF.loadThis(input);
}
I assume you have an instance of MainForm already, and that's what creates an instance of AnotherForm.
Inside the event you posted, you're actually creating an entirely new instance of MainForm, never showing it, and then it's destroyed anyway when AnotherForm closes.
The reason you see nothing in the text box is because you're looking at the original instance of MainForm, which you haven't actually changed.
One quickie way of fixing this would be passing a reference to the original MainForm into AnotherForm:
public class AnotherForm
{
private MainForm mainF;
public AnotherForm(MainForm mainF)
{
this.mainF = mainF;
}
...
...
private void listView1_ItemActivate(object sender, EventArgs e)
{
...
mainF.inputTextBox.Text = input;
...
}
}
Note: Instead of having AnotherForm aware of MainForm, you might want to switch it around and create a public property in AnotherForm like this:
public class AnotherForm
{
public InputValue { get; private set; }
private void listView1_ItemActivate(object sender, EventArgs e)
{
...
InputValue = input;
...
}
}
Which you can then access from MainForm when the other form is closed:
private void SomeMethodInMainForm()
{
var newAnotherForm = new AnotherForm();
newAnotherForm.ShowDialog();
var inputValueFromAnotherForm = newAnotherForm.InputValue;
// do something with the input value from "AnotherForm"
}
If your MainForm has already been created you cannot just create another one in order to access it and set properties. You've created two separate MainForms (though the 2nd one is hidden because you never showed it).
It sounds like what you want to do is a modal dialog pattern. Your MainForm is the main window in your application. You want to have a 2nd form pop up when you click on a menu link. This is called a dialog. Then when you close that dialog you want your MainForm to retrieve a value as a returned result of the dialog.
In your MainForm the event handler which handles the menu item click should look something like this:
private void pickSomethingMenuItem_Click(object sender, EventArgs e)
{
using (var picker = new PickerDialog())
{
if (picker.ShowDialog(this) == DialogResult.OK)
{
LoadSomething(picker.SomethingPicked);
}
}
}
Then the following code would be inside your dialog form:
public string SomethingPicked { get; private set; }
private void somethingListView_ItemActivate(object sender, EventArgs e)
{
SomethingPicked = somethingListView.SelectedItem[0].ToString();
DialogResult = DialogResult.OK;
}
Notice how I named all of the objects with meaningful names. Well, except for "Something". It was impossible to tell from your code what you were actually using the dialog to pick. You should always use meaningful names for your objects and variables. Your code is almost completely nonsensical.
And you should almost never make a control on a Form public like you have with your inputTextBox. You should always expose values you want to share as public properties.
On this presented solution, you could do five main things in order to achieve what you want to do, namely:
1) Declare a global object for AnotherForm in MainForm
2) Initiate a FromClosing event handler for AnotherForm in MainForm
3) Make a public property or field in AnotherForm
4) Before closing in AnotherForm you save it the public property mentioned above
5) In the MainForm get the public property from AnotherForm
Here is the code:
MainForm
public partial class MainForm : Form
{
AnotherForm anotherForm; // Declare a global object for AnotherForm
public MainForm()
{
InitializeComponent();
}
private void showToolStripMenuItem_Click(object sender, EventArgs e)
{
anotherForm = new AnotherForm(); // when Menu Item is clicked instantiate the Form
anotherForm.FormClosing += new FormClosingEventHandler(anotherForm_FormClosing); // Add a FormClosing event Handler
anotherForm.ShowDialog();
}
void anotherForm_FormClosing(object sender, FormClosingEventArgs e)
{
inputTextBox.Text = anotherForm.listViewValue; // get the Value from public property in AnotherForm
}
}
AnotherForm
void listView1_ItemActivate(object sender, EventArgs e)
{
listViewValue = listView1.SelectedItems[0].Text; // Get the listViewItem value and save to public property
this.Close(); // Close
}
public String listViewValue { get; set; } // public property to store the ListView value
One thing to note here in comparison to your code I didn't use ToString() in ListView.SelectedItems:
listView1.SelectedItems[0].ToString();
But instead use the Text Property:
listView1.SelectedItems[0].Text;

Accessing a Parent form button from a Child form button

I have a program that has a parent form which then creates a child form. Upon clicking the updateButton within the child form, I want the searchButton within the parent form to fire.
However I get an error for protection reasons. I have tried setting everything Public just to see, still wont work for me.
Error 1 'SalesSystem.SystemForm.searchButton' is inaccessible due to
its protection level SalesSystem\UpdateForm.cs 111 20 SalesSystem
This is what I have so far.
Parent Code
namespace SalesSystem
{
public partial class SystemForm : Form
{
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
}
Child Code
namespace SalesSystem
{
public partial class UpdateForm : Form
{
public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
{
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
SystemForm parent = (SystemForm)this.Owner;
parent.searchButton.PerformClick();
this.Close();
}
}
}
Your searchButton button control is set to private by default in WinForm. You've said you set everything to public but I assume you mean you've set everything in the code you've posted to public. There are a few ways to fix this. The direct fix would be to simply go to Visual Studio designer, select the button, and set its Modifier property to internal or public.
However, it seems you're closing your form straight after so I'd just have my parent form subscribe to the FormClosing event of the form.
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.FormClosing += (s, o) =>
{
//your code for what the parent class should do
};
upForm.ShowDialog(this);
If you're not closing the form then you can create your own event handler that your parent form subscribes to.
You have 2 options:
create a public void search() method in your parent form. Then, instead of accessing the the button on the parent form and invoking its click event, you run the search code directly. The new method is not tied to a GUI element and accessing it from a different form is no problem.
The better solution is to create a delegate. A delegate is an execution target that will be assigned at run time. The parent form still has a public void search() method. And when it creates the child form, it will pass the name of that function as parameter. The child form has no knowledge about the parent form (as opposed to the first option where the child MUST know that there is a method called search()). When it is time to inform whoever created the child form, the delegate is called. This is a small example:
public partial class SystemForm : Form
{
public delegate void dSearch();
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
search();
}
private void search()
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname, search);
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
}
And the child form:
public partial class UpdateForm : Form
{
private SystemForm.dSearch _target;
public UpdateForm(string selectedPerson, string dbdirec, string dbfname, SystemForm.dSearch target)
{
_target = target;
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
_target();
this.Close();
}
}
You should use the "Model View Controller" or "Model View Presenter" pattern to approach this kind of thing.
Each form should only be concerned with displaying its contents to the user. When it comes to responding to UI events such as button clicks, each form (i.e. each "View") should simply raise an event which informs the controller/presenter that something has happened.
The controller/presenter should then respond appropriately. Then the logic that wires together different forms (such as the parent and child forms in your example) is encapsulated in the Controller class. Such logic does not really belong in either of the forms.
I wrote an example that demonstrates a simple design to do this sort of thing in another answer some time ago. Rather than copy/paste it all here, I'll just give you a link to it:
How to make Form1 label.text change when checkbox on form2 is checked?
You'll have to scroll down to see my answer. It's broadly similar to what you're doing; hopefully it will make sense to you! Follow the instructions to make a test application and run it to see what happens.
I'm tired and might be missing something but that is correct behaviour.
Your child form does not directly inherit from your parent form.
Your parent form has a protected level, so only it and classes that extend it can access the method.
2 solutions:
Change your child form to:
public partial class UpdateForm : SystemForm
Change method to public
public void searchButton_Click(object sender, EventArgs e)
You could expose a Search Event from your UpdateForm and subscribe to this event in the SystemForm
namespace SalesSystem
{
public partial class SystemForm : Form
{
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.OnSearch += Search;
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
private void Search(string searchParameter)
{
....
}
}
namespace SalesSystem
{
public delegate void SearchEventHandler(string searchParameter);
public partial class UpdateForm : Form
{
public event SearchEventHandler OnSearch;
public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
{
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
OnSearch("SearchThis");
this.Close();
}
}
}

Categories

Resources