Prevent to close parent window if child windows are active - c#

I am developing multiple instance WPF application. Application has a grid in a main screen and on double click of grid row, it opens child window. It has also functionality to open multiple child windows on double click of grid row from main screen.
Can anybody help me to prevent parent window to be close if child windows are active? So user can not able to close main window if child windows are active.

Set Owner property for those childs to Main Windows:
private void Button_Click(object sender, RoutedEventArgs e)
{
var wnd = new Window();
wnd.Owner = this;
wnd.Show();
}
Then in Main Window closing event handler:
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (this.OwnedWindows.Count > 0)
{
MessageBox.Show("Child windows exists, you have to close'em first");
e.Cancel = true;
}
}
As a final point it could be helpful for you to know that you can get from anywhere in your code the app main windows with this:
System.Windows.Application.Current.MainWindow
So if you are using MVVM the above will help you in setting the Owner property.

You have two options:
1- You can use ShowDialog() to open the child window, but user can't interact with the parent window till the child is closed.
2- You can check all windows that are currently opened by checking
Application.Current.Windows
and then you can determine whether you want to close your window or not
Edit:
add the following event handler to your Parent.Closing event
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
foreach (var item in Application.Current.Windows)
{
Window window = item as Window;
if (window.Title == "YourChildWindowTitle")
{
// show some message for user to close childWindows
e.Cancel = true;
break;
}
}
}

In window closing command pass that if the child window is open disable closing functionality.
Or
you what you can do is make canexecute = false when a pop up is open and closing command is triggered.

Attach a function to the main window's 'Closing' event, and check to see if the child window is open. if it is, set
e.cancel = true;

Related

Access controls located on the main form when the child form closes

I have created a main form which is always visible to users... its got some menu options. This form (Main) has got a number of hidden buttons which I am trying to unhide from another child form once the child form closes. My question is..."how do you transfer control from child to Main or reference the buttons on the Main form once the child have close. Thanks in advance for all help and suggestions. Here is what I have got so far:-
//This event is in the child's form..
private void Registerbutton_Click(object sender, EventArgs e) {
.
. // carry out some work and close
.
}
this.Close();
Showbuttons();//custom procedure
//custom procedure use to display all the hidden buttons on Main form
public void Showbutton(){
foreach (Control c in ((Main)MdiParent).Controls){
if (c is Button){
((Button)c).Show();
}
}
}
Subscribe to the child form's FormClosed event:
var childForm = new ChildForm();
childForm.FormClosed += ChildFormClosedHandler;
childForm.Show();
Then once the child form closes it will show all the buttons that are direct descendants of the form.
private void ChildFormClosedHandler(object sender, FormClosedEventArgs e)
{
foreach (Button button in this.Controls.OfType<Button>()){
button.Visible = true;
}
}
If you only want the buttons to be shown after some specific function then you may need to set some property on the child and do a check through the sender argument.

Why Won't Form Get Focus?

I have a form that is launched modally like this:
private void find_street_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
Form findForm = new FindStreet();
findForm.ShowDialog();
this.WindowState = FormWindowState.Normal;
}
The form launches correctly, and the cursor is in the first text box, whose TabIndex is set to 1.
Along with the InitializeComponent(); call, these commands are present.
public FindStreet()
{
InitializeComponent();
this.TopMost = true;
this.BringToFront();
this.Focus();
}
I have looked at and tried a number of examples. The cursor appears in the correct control, but the form's window does not have the focus. The problem is that if a user starts typing, even though the newly launched form is visible, those keystrokes are not going into the text box.
Remove the code in public FindStreet() and in load event of FindStreet add:
this.TopMost = true; //i don't know why you need this.
this.Activate();
When you minimize your main form the next one in z-order get the cursor. this.Focus() doesn't do anything. You need to Activate the dialog.
A dialog requires an owner, that cannot be a minimized window. Now accidents start to happen, starting with your WindowState assignment. Your app doesn't have a window left that can receive the focus so Windows is forced to find another one, that will be one owned by another application. Same problem happens when you close the dialog.
You can still get the intended effect, you must hide your main window after the dialog is displayed, show it again before the dialog closes. That requires a bit of hackorama:
using (var dlg = FindStreet()) {
// Show main window when dialog is closing
dlg.FormClosing += new FormClosingEventHandler((s, cea) => {
if (!cea.Cancel) this.Show();
});
// Hide main window after dialog is shown
this.BeginInvoke(new Action(() => {
this.Hide();
}));
dlg.StartPosition = FormStartPosition.Manual;
dlg.Location = this.Location;
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
// etc...
}
}
And remove the hacks from the FindStreet constructor. Watch out for event order if you have a FormClosing event handler in FindStreet, be sure to override OnFormClosing() instead.
If you want to set a specific control as the current active control then try this:
this.ActiveControl = myTextBox;
This will place the cursor you want as the main focus, when the form loads. So try this out:
public FindStreet()
{
InitializeComponent();
this.TopMost = true;
this.BringToFront();
this.Focus();
this.ActiveControl = myTextBox;
}
Here is the link to Focus() which should explain why your focus call was not working.

C# - How Do I Close Main Form Together With Child Forms (while child windows must close ONLY when main form is closing)

I have a main window and a few child windows. Child windows contain some data so I don't want them to be closed. So I hide them while in FormClosing I set e.Cancel = true;
But when I want the main window to close (exit application). I have some trouble to exit it. First it wouldn't close. But with an extra variable to note that I'm closing I need 2 clicks to actually close it (problem is before onFormClosing(mainWIndow, ...) is executed the framework tries to close the children which will hide themselves first).
// main and child windows have this as form closing event proc
private void onFormClosing(object sender, FormClosingEventArgs e)
{
if (sender == this) // main
{
exitApp = true;
}
else
if (sender == formChild) // child
{
if (!exitApp)
{
e.Cancel = true;
formChild.Hide();
}
}
}
How can I close them all in 1 click ?
I would also like to avoid Application.Exit(); because I need to make sure all threads close properly. So best would be a clean close.
You can force the application with Application.Exit().
Found the solution myself:
// ...
if (sender == this) // main
{
exitApp = true;
FormClosing -= onFormClosing;
Close();
}
// ...

Detect if user has moved window in WPF

I have seen a couple posts on this, but they don't necessarily answer my question exactly.
I have a parent window that on its LocationChangedevent, it will grab a child window and move that along with it in a "snapped" fashion. I want to find an event and set a boolean value on the child form that would say "if the user has manually moved me, I will not re-attach to the parent."
Is there a way to detect if the user has moved the child window, rather than my parent window moving it?
I hope this makes sense.
Assuming you are using your child Window's Owner property to associate your parent Window to the child Window I would use an events-based approach.
In your child Window create an event that notifies listeners to disassociate (detach) the child Window from its parent:
public event EventHandler<EventArgs> DetachOwner;
You next need to determine when this event should be raised. For this we'll use three events in the child Window: Activated, Deactivated and LocationChanged.
LocationChanged will tell us when the child Window has moved but we'll need to filter out cases when the child Windows moves because it's following the parent Window. To do this we will need to know if the child Window is moving and it has focus. To track the focus state of the child Window create a bool field called HasFocus and set HasFocus to true in the Window's Activated event handler, and false in the Window's Deactivated handler.
Add this to your child Window:
private void Window_LocationChanged(object sender, EventArgs e) {
if (HasFocus) {
if (DetachChild != null) {
DetachChild(this, EventArgs.Empty);
}
}
}
bool HasFocus;
private void Window_Activated(object sender, EventArgs e) {
HasFocus = true;
}
private void Window_Deactivated(object sender, EventArgs e) {
HasFocus = false;
}
In the parent Window you'll subscribe to the child Window's DetachOwner event when you instantiate the child Window:
_child = new Child();
_child.Owner = this;
// Subscribe to the DetachOwner event.
_child.DetachChild += Child_DetachOwner;
This DetachOwner handler simply sets the child Window's Owner property to null:
void Child_DetachOwner(object sender, EventArgs e) {
((Child)sender).Owner = null;
}
You can expand on this approach to reattach the child Window to it's parent by creating a similar AttachOwner event in the child Window with a handler in the parent Window:
void Child_AttachOwner(object sender, EventArgs e) {
((Child)sender).Owner = this;
}

Lock menu item when window open, unlock when closing

I have a window that I want to allow only one instance of it to be open at a time. They can open / close the window, but can't have multiple copies of the same window open at a time.
I have a menu with an option that when clicked, opens the ProductSelection window. ListProductList is my button:
private void ListProductListCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = _productListCanExecute;
//_productListCanExecute = !_productListCanExecute;
}
private void ListProductList(object sender, ExecutedRoutedEventArgs e)
{
_productListCanExecute = false;
ProductSelection pl = new ProductSelection(productCategoryList, productStyleList, productList);
pl.Show();
}
Notice that I set the e.CanExecute of the ListProductList button to false to ensure that the event handler doesn't run and therefore doesn't open more windows.
Now, how can I detect that the ProductSelection window has closed in order to set the _productListCanExecute back to true? It's not a modal window, because I want to allow them to do other things.
Probably the easiest solution here is to make the pl variable a global.
Whenever the button is clicked, just "show" that existing window.

Categories