C# Closing Event on Child-Form if Closing Application - winforms

Good morning guys.
I have a little problem. If I close my Mainform (Windows-App) when my second form is opened, the second form closes without using my secondForm_FormClosing Event.
Anyone have a idea to handle this?
secondForm_FormClosing

The 2nd form is an Instance of a Form/Class itself so unless you have it setup as an MDI application the 2nd form won't receive the Closing or Closed event because the program is exiting.
You can tap into the 2nd Forms FormClosing event from Form1's closing event, this is one of many ways:
public Form1()
{
InitializeComponent();
frm2.FormClosing += new FormClosingEventHandler(form2_FormClosing);
frm2.Show();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
form2_FormClosing(null, e);
}
private void form2_FormClosing(object? sender, FormClosingEventArgs e)
{
// This will only get called "directly" when the second form is
// closed otherwise it will always be called from Form1_FormClosing.
}

Related

Winforms ContextMenuStrip wont open when Opening event is handled

I'm moving a Winforms app from VB to C#. I have a TrueDBGrid with a ContextMenuStrip thats pops up on a right click. When I don't handle the mnuContext Opening event the menu pops up. When I do handle the event the handler is called but the menu wont popup - even if the handler does nothing.
The code below has been trimmed to just have the handler call, so it's not what the code is doing, just the existence of the handler itself.
public void MenuOpeningHandler(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = false;
}
Setup code is:
public InvoiceListForm()
{
InitializeComponent();
mnuContext.Opening += MnuContext_Opening;
}
private void MnuContext_Opening(object sender, System.ComponentModel.CancelEventArgs e)
{
MenuOpeningHandler(sender, e);
e.Cancel = false;
}
The event appears to be stopped/Cancelled instead of continuing to propagate and open. Any idea what could be missing?

Closing a Windows Form, using the Close Window button, when a Validation Message is showing

I have a Windows form that has a validation event on a textBox so that if the value of that TextBox is a value that already exists it triggers a validation error.
private void txtUsername_Validating(object sender, CancelEventArgs e)
{
var alreadyExists = _logic.UserIdExists(txtUsername.Text.Trim());
if(alreadyExists)
{
errorProvider1.SetError(txtUsername, "This Userid already exists, please choose an alternative");
e.Cancel = true;
}
}
private void txtUsername_Validated(object sender, EventArgs e)
{
errorProvider1.SetError(txtUsername, "");
}
this.txtUsername.Validating += new System.ComponentModel.CancelEventHandler(this.txtUsername_Validating);
this.txtUsername.Validated += new System.EventHandler(this.txtUsername_Validated);
This results in an error image appearing next to that textBox along with a tooltip error message.
If I try and close the application, using the Close button at the top of the window, at this time I cannot as the above Event keeps firing even when I try and close the window (due to me taking focus away from the Text box).
Is there a way of closing the window, without resorting to creating an additional Close button on the form?
Based on your description, you want to maintain the default auto-validation behavior yet allow the Form to be closed using the title bar close button. I have observed that the Form.Closing event is raised in such a circumstance, however its argument Cancel property is preset to true. A simple solution is to handle this event and set e.Cancel = false. Implement any logic in the handler that you deem necessary.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing) e.Cancel = false;
}

Winform Timer isn't running if statement when criteria is met

Hi I've come across either a weird bug or I'm not understanding something.
To cut a long story short I've had everything I'm wanting to work on my form working fine, I then decided to turn the form into an options menu so it was no longer the first form that appears when the application is launched and is shown after I click a button on a different form with the code
private void ShowOptionsButton_Click(object sender, EventArgs e)
{
formHomePage.Show();
}
And for some reason a timer if statement is no longer working:
private void StartSubCheckT_Tick(object sender, EventArgs e)
{
if (subliminalMessages.Count > 0)
{
MessageBox.Show("list greater than 0 if");
StartSubB.Enabled = true;
}
there are other if statements below but are irrelevant and the point of this is to make a button usable once a list is greater than 0. I've created another test button to display the value and it shows that the sublminalMessages list is greater than 0
private void testbutton3_Click(object sender, EventArgs e)
{
MessageBox.Show(subliminalMessages.Count.ToString());
}
Which outputs at 1 which it should be from some other code that adds a value in at the beginning. But for some reason even with the subliminalmessages.count being greater than 0 the if statement is no longer being called ever since I'm making the form appear being called from another form from the button code above.
The subliminalMessages list is being populated and created on the same form
public List<string> subliminalMessages = new List<string>();
private void Form1_Load(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(Settings.Default["Subliminal1"].ToString()))
{
subliminalMessages.Add(Settings.Default["Subliminal1"].ToString());
MessageBox.Show("If worked");
}
}
There is a value in the Setting.Default that is being added
The button and timer are on the same form and the timer in question is enabled.
Does anyone know why?
Thanks
I'll have a stab at giving you an answer. But it's a little swerve from what you're doing now.
From what I understand of your code you are using the timer to enable/disable the StartSubB button. Or maybe just enable it.
Instead of relying on the timer which appears to not work why not use a BindingList<string>. This has an event called ListChanged which you can handle and then enable/disable your button.
Here's a test form I created:
public partial class Form1 : Form
{
BindingList<string> items;
public Form1()
{
InitializeComponent();
button3.Enabled = false;
items = new BindingList<string>();
items.ListChanged += Items_ListChanged;
}
private void Items_ListChanged(object sender, ListChangedEventArgs e)
{
button3.Enabled = items.Count > 0;
}
private void btnAdd_Click(object sender, EventArgs e)
{
items.Add("a");
}
private void btnRemove_Click(object sender, EventArgs e)
{
if (items.Count > 0)
items.RemoveAt(items.Count - 1);
}
}
I have a BindingList<string> called items. This is analagous with your subliminalmessages list but it's a BindingList. This type of list has a ListChanged event that fires when items are added or removed from the list. In the constructor we new up the items list and subscribe to the ListChanged event.
When the Items_ListChanged event fires button3 is enabled or disabled based on whether items.Count > 0 or not.
In btnAdd_Click we just add an item to the list.
In btnRemove_Click we check that there are some items then remove the last one.
If you were to run this you'd see that when we click the Add button, button3 gets enabled. If we click the Remove button we'll see button3 get disabled.
The only limitation of BindingList is that you can't add a range by passing in another List.
If you implement this and your button still doesn't activate then you'll probably need to post some more code. Strip out all the irrelevant stuff and put it in a new project that demonstrates the failure of the condition and either copy the code here or provide a link to download the project. The only reason the if statement should fail is if the list is actually empty.

WPF close secondary window before main window

I have 2 windows in a WPF application, and If I close the Main one, I want to close the other too.
I achieved this by setting in my App.xaml:
ShutdownMode="OnMainWindowClose"
The 2 windows have a Window_Closing event in which I de-initialise some components. Now what I want to achieve is: if I close the MainWindow, the Window_Closing event of the second window must execute before the closing event of the Main one, because the de-init of the second one has to be executed before the first. Any idea on how can I achive this?
Use the Application.Current.Windows collection. It contains the list of all the windows of your app; you can iterate through them and operate on them.
In this case, you can write:
public void MainWindow_Closing(object sender, CancelEventArgs e)
{
foreach (Window w in Application.Current.Windows)
{
if (w.Title == "Secondary Window") // <-- or whatever check you want to identify the secondary Window
{
w.Close();
break;
}
}
}
This allows you to gain a flexible behavior, for example you can close ALL the secondary windows, not just one.
Could you simply call the Close() function of the second window from the main window Window_Closing event?
void MainWindow_Closing(object sender, CancelEventArgs e)
{
secondaryWindow.Close();
...
}
Close all windows but the MainWindow in the Closing event handler. This should work:
void MainWindow_Closing(object sender, CancelEventArgs e)
{
foreach (Window w in Application.Current.Windows)
{
if (w != this)
w.Close();
}
//handle clean up for MainWindow here...
}
You might also want to consider to handle the Application.Current.Exit event to perform the cleanup of all windows in one place.

Windows.Activated in wpf fires multiple times

Hi I have a code to be written while window(WPF window) activate like clicking on the window or using alt/tab. The window is the child of a main form (windows app). I have used ToolWindow as the windowstyle.
It has a xamdatagrid which has to updated on activation
Problem is it fires multiple times. It should be fired once. I don not want my code to run multiple times
How to make it work. please help
From the Window.Activated Event page on MSDN:
Occurs when a window becomes the foreground window.
The Window.Activated Event is supposed to be called multiple times, so perhaps it is not the best event for you to handle. Alternatively, you could add a bool isFirstTime variable and use it to restrict your code to only being called once. Take this example:
private bool isFirstTime = true;
...
private void WindowActivated(object sender, EventArgs e)
{
if (isFirstTime)
{
isFirstTime = false;
// do something here just once
}
}
However, as (from the linked page)...
A window is activated (becomes the foreground window) when:
• The window is first opened.
• A user switches to a window by selecting it with the mouse, pressing ALT+TAB, or from Task Manager.
• A user clicks the window's taskbar button.
... you may find that this will not work for you.
I got it done.
I was using the below code
private void OnAttributeHistoryWindowActivated(object sender, EventArgs e)
{
var win = ((RoutedEventArgs)(e)).Source as AttributeHistoryWindow;
//My Code
}
The first line of code was firing back the Activated event. And it never goes to the next line of my code.
Now I used below code and it works.
private void OnAttributeHistoryWindowActivated(object sender, EventArgs e)
{
var win = sender as AttributeHistoryWindow;
//My Code
}
Now it fires once.

Resources