We have a big windows forms solution and need to get an event every time a form is opened or closed
for telemetry. All forms should be tracked across the entire application.
I found a collection of all the open forms through Application.OpenForms but I don't think it is possible to observe it for changes since it is a FormCollection.
Is there any way of doing this with minimal changes to the existing forms? Perhaps something related to the application process?
You can create a static boolean variable in each form and set the variable to true when the form is shown(form_shown_event) and set it to false when the form is closing(form_closing_event). Then you can access the variable as Form1.formOpen to check if the form is already open or not.
A sample for your code:
public partial class Form1 : Form
{
public static bool formOpen = false;
public Form1()
{
InitializeComponent();
this.Shown += Form1_Shown;
this.FormClosing += Form1_FormClosing;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
formOpen = false;
}
private void Form1_Shown(object sender, EventArgs e)
{
formOpen = true;
}
}
Related
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
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();
}
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 am developing a windows mobile application, and I want to do something after a form (a loading screen) is displayed to the user.
normally, I have a Form.Shown event, but with the .net compact framework v3.5, I can't find this event.
Does anyone know of an equivalent to the Shown event or a simple workaround I could use? I don't want to do my own multi-threading if I can help it.
The only thing I can think of would be a bit of a hack, when your form is shown, if it has a default control then it will receive the focus. The Focus event will fire during the initial load before the form is shown, but will be fired the second time when it is visible. put a boolean in the Activate event that is set with the first Activates, then test in the default controls Got Focus event.
Other option would be to use a Timer. Set the Interval to something like 10, start it at the end of your Form Load event and then run your startup specific code.
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
//Do something
}
An example per Hans's Comment:
public partial class Form1 : Form
{
public delegate void DoWorkDelegate();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
BeginInvoke(new DoWorkDelegate(DoWorkMethod));
}
public void DoWorkMethod()
{
//Do something
}
}
I have a multiple windows form application (frmMian, frmSteg and frmCrypt) in c#. From the main form (frmMain), I can call the other (two) forms. How can Iuse the form closing event similar to that used in VB to return to the main form whenever I exit any of the two forms?
FrmSteg frmstego = new FrmSteg();
FrmCrypto frmcrypt = new FrmCrypto();
private void btnsteg_Click(object sender, EventArgs e)
{
frmstego.Show();
this.Hide() ;
}
private void btncrypto_Click(object sender, EventArgs e)
{
frmcrypt.Show();
this.Hide();
}
Use the Form.Closed event on the child windows.
frmstego.Closed += (s, e) => {
this.Show();
};
frmcrypt.Closed += (s, e) => {
this.Show();
};
Try placing a Singleton accessor on the main form like this. And then in the constructor of the main form set _instance = this.
private static <MainFormType> _instance;
public static <MainFormType> Instance
{
get
{
return _instance;
}
}