I have C# WinForms code as follows to close all child forms when I open a new child form:
private void CloseAllActiveForms(Form[] MdiChildren)
{
Form[] childArray = MdiChildren;
foreach (Form childform in childArray)
{
childform.Close();
}
}
How can I use in WPF windows?
I tried the below code, but it will close all windows including the Parent and the Active window.
private void CloseAllWindows()
{
for (int intCounter = App.Current.Windows.Count - 1; intCounter >= 0; intCounter--)
{
Application.Current.Windows[intCounter].Close();
}
}
Thanks.
As far as I know, MDI support for WPF is limited, so try using the Tag attribute when you create your pseudo-child windows:
Window child = new Window();
child.Tag = "mdi_child";
Then, in your loop, modify it like this:
foreach (Window win in App.Current.Windows)
{
if (!win.IsFocused && win.Tag.ToString() == "mdi_child")
{
win.Close();
}
}
Note that for the above solution to work, ALL windows must have a Tag attribute, or else an Exception will be thrown at win.Tag.ToString().
Here is a method I use in WPF to close all child windows of my program, this code goes in the main window.cs file, but you could modify if(item!=this) to check for a particular window:
foreach(Window item in App.Current.Windows)
{
if(item!=this)
item.Close();
}
No faffing around with sub-classes or more lists (especially as the code already has a list of windows associated with it.)
If you wanted to selectively close windows then you could always modify the if statement to use a variable on the window class or check one of the pre-existing variables (such as a the class of the parent window) on the base window class.
Related
when i move between forms buttons works as expected, but when im closing my custom pop up only seconds click on any button will trigger it
this is the code im using to load my custom popup
public void loadPopUp(Form from, Form to)
{
to.Tag = from;
to.Show(from);
}
and this is the code my using to close my custom popup
public void closePopUp(string formName)
{
for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
{
string name = Application.OpenForms[i].Name; //for debugging only
if (Application.OpenForms[i].Name == formName)
Application.OpenForms[i].Close();
}
}
note: this is not asp.net application
You should have something else in your code or you make something with the main window that changes the normal behavior of the forms engine. I have tried to build a sample app with LinqPAD using the code above and I have a normal behavior as expected. When I close the popup the focus is restored to the main form.
Nevertheless you could use the main form saved instance in the Tag property to call the Activate method and restore the focus to the main form.
public void closePopUp(string formName)
{
// No need to loop over all application OpenForms if you just want
// to close this popup
// for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
// {
// string name = Application.OpenForms[i].Name; //for debugging only
// if (Application.OpenForms[i].Name == formName)
// Application.OpenForms[i].Close();
//}
var mainForm = this.Tag as Form;
this.Close();
if(mainForm != null)
mainForm.Activate();
}
Note, I use a cast to the base Form class, so your code doesn't depend on the popup created by a particular class instance. This is possible because Activate is a base class method.
I have a WPF Application. I need to minimize and restore the main window after instantiate it to obtain focus. I am using something like the following class but it is not making what I want because when the window is restored it has an invalid size. I've tried to modify the width and height but it is not working.
public class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ConfigureWindow();
}
public void Show()
{
base.Show();
UpdateWindowPositionAndSize();
base.WindowState = WindowState.Normal;
base.Show();
}
private void ConfigureWindow()
{
base.ShowActivated = true;
this.Focusable = true;
if (base.IsActive == false)
{
base.Activate();
}
if (base.IsFocused == false)
{
base.Focus();
}
base.WindowState = WindowState.Minimized;
}
private void UpdateWindowPositionAndSize()
{
this.Top = (SystemParameters.WorkArea.Height - this.Height) / 2;
this.Left = (SystemParameters.WorkArea.Width - this.Width) / 2;
}
}
What I am doing wrong? There is another way to obtain the focus? Sorry if the question is too newby.
UPDATED:
What is the specific need?
I need that my WPF Application appears on focus and active after launch it.
why?
Since it will be launched by a Windows (7, 8.1 and 10) User after explicitly click on a submenu from a file context menu (meaning a Shell Extension). This is 'why' my client wants that appears on front of the screen and focused.
when?
After instantiate the window.
how?
Well, I made some research and I found several ways to do this. One of the methods that I've tried is minimize the window and the restore it. There where others like using the functions SwitchToThisWindow or setforegroundwindow, but I would like to know if there are better options.
What happen when I've tried minimize and restore the window? (correct size)
Well, this way gives me focus on the main window, but it change the width and heigh. By default I define them on 300 (w) and 300 (h), but after changing the windows state to normal these values change to 400 (w) and 350 (h).
If I dont do anything, it has the focus right away?
... No ...
UPDATE2:
I choose the method used in the next link:
https://www.roelvanlisdonk.nl/2014/09/05/reliable-bring-external-process-window-to-foreground-without-c/
I am not quite sure what your problem is but maybe this can help.
1.) Remove StartupUri="MainWindow.xaml" from App.xaml;
2.) Add Startup="Application_Startup"
Your App.xaml.cs should look like this:
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
//Create new Instance of MainWindow
MainWindow mainWindow = new MainWindow();
//Set Properties of that Window
UpdateWindowPositionAndSize(mainWindow);
//Show it !
MainWindow = mainWindow; //This is the Application.MainWindow Property - not needed
mainWindow.ShowDialog();
}
private void UpdateWindowPositionAndSize(MainWindow mainWindow)
{
//Do your modifications here
mainWindow.Top = (SystemParameters.WorkArea.Height - mainWindow.Height) / 2;
mainWindow.Left = (SystemParameters.WorkArea.Width - mainWindow.Width) / 2;
}
}
So basically you just modify your Window until all is done.
There is no need to show it first, change its position and then bring it back on - if I got your "usecase" right.
Because to me it looks like you are hiding the window to do your "positioning".
But I think it's better to do it when Initializing.
Just a short comment on your code so far:
ConfigureWindow() is only doing minimize.
The rest of your code is useless cause obviously the window loses focus when it's minimized.
I would suggest not to create methods with names that already exist.
This will only lead to cusfusion.
If you got problems with WindowState = WindowState.Minimized; you can try Hide() and Activate().
By default when calling Window.Show(); the window will have focus. Check here for details.
Also after setting WindowState = WindowState.Minimized; you don't need to call base.Show(); again - the window is shown already. WindowState = WindowState.Normal; should do the job.
I need to be able to close a form and have it close all other forms besides the switch board. I tried using this code but it also closes the frmSwitch even though I attempted to code it to close all but that. Where did I go wrong? I am supposed to use the actual name of the form correct?
Form[] forms = Application.OpenForms.Cast<Form>().ToArray();
foreach (Form thisForm in forms)
{
if (thisForm.Name != "frmSwitch") thisForm.Close();
}
You need to check if thisForm is frmSwitch, and then close the rest.
foreach (Form thisForm in Application.OpenForms)
{
if (!(thisForm is frmSwitch))
thisForm.Close();
}
You also don't have to use Cast<Form> and ToArray, you can enumerate FormCollection
This will work assuming you are closing from your "main form"
var list = Application.OpenForms.Cast<Form>().ToArray();
foreach (Form item in list)
{
if (item.Equals(this)) continue;
item.Close();
}
I need to show a form exactly in front of another form, this lead me to the following question.
How come a form can have a start position as CenterParent while having the field this.Parent equals to null?
It must know the parent in order to position itself correctly, which it does, but the Parent field is not set. This is odd. Am I missing something?
Form2 f = new Form2();
f.ShowDialog();
Thats all I do on the child form. The parent is set to default windows position. No matter where I move the parent form, the child is shown in the center of the parent.
The information about the owner is passed to the created dialog via the API call (you can see that in Reflector within the ShowDialog(IWin32Window owner) method):
UnsafeNativeMethods.SetWindowLong(new HandleRef(this, base.Handle), -8, new HandleRef(owner, handle));
When there is no owner specified in ShowDialog call the owner variable is calcualated via the GetActiveWindow API call:
IntPtr activeWindow = UnsafeNativeMethods.GetActiveWindow();
IntPtr handle = (owner == null) ? activeWindow : Control.GetSafeHandle(owner);
To get access to the Owner f dialog form you can use the GetWindowLong API call:
IntPtr ownerHandle = NativeMethods.GetWindowLong(nonModalForm.Handle, -8);
The difference between a parent and an owner of a window is a bit muddled in Winforms. In this context, CenterParent really means CenterOwner. Not a Windows capability, it is implemented in Winforms, done by the base Form.OnLoad() method. A dialog should always have a owner, it goes out hunting for one when you don't specify one in the ShowDialog() call. Which uses GetActiveWindow() as the best guess.
To see this for yourself, overload OnLoad in the dialog form, like this:
public partial class Form2 : Form {
public Form2() {
InitializeComponent();
this.StartPosition = FormStartPosition.CenterParent;
}
protected override void OnLoad(EventArgs e) {
//base.OnLoad(e);
}
}
And note that it no longer centers on the owner.
You can see the relevant code in the Reference Source, Form.cs class, OnLoad method:
if (GetState(STATE_MODAL)) {
FormStartPosition startPos = (FormStartPosition)formState[FormStateStartPos];
if (startPos == FormStartPosition.CenterParent) {
CenterToParent();
}
else if (startPos == FormStartPosition.CenterScreen) {
CenterToScreen();
}
}
I believe this information is stored internally by .NET Framework for some reason. Anyway, if you want to have access to the parent form you can set it to Owner property of the child form:
Form form = new Form();
form.Owner = this;
form.Show();
Then in the child form you can access the parent form using the Owner property. When a form is owned by another form, it is minimized and closed with the owner form. Owned forms are also never displayed behind their owner form, which is exaclty what you need if I understood you right.
This code will open the dialog in the middle of the parent TAG.
ObjectDistrubution od = new ObjectDistrubution();
od.StartPosition = FormStartPosition.CenterParent;
od.ShowDialog();
i have a mdi form and there is lot of other form linked with the menu strip. when i click any other menu item then there should be close previous open form inside the mdi parent form.
Here is a more succinct, modern, and surgical way to close all MdiChild forms:
static void CloseAllMdiChildForms()
{
foreach (var form in Application.OpenForms.Cast<Form>().Where(f => f.IsMdiChild).ToArray()) // ToArray necessary to build a snapshot
form.Close();
}
However, it sounds like what you want is to have only one child form open at any given time. If that is the case, MDI is not the right tool for the job. You can build UserControls and swap them into and out of your main application form instead.
Call this method when you want to open a new form:
private void CloseAllForms()
{
Form[] formToClose = null;
int i = 1;
foreach (Form form in Application.OpenForms)
{
if (form != this) //this is form1
{
Array.Resize(ref formToClose, i);
formToClose[i - 1] = form;
i++;
}
}
if (formToClose != null)
for (int j = 0; j < formToClose.Length; j++)
formToClose[j].Dispose();
}
Mitja
This is best one:
static void CloseAllMdiChildForms()
{
foreach (var form in Application.OpenForms.Cast<Form>().Where(f => f.IsMdiChild).ToArray()) // The ToArray is necessary to build a snapshot
form.Close();
}