Is there any possibility to handle an event on a disabled WPF window? The main window is disabled by .ShowDialog() from other windows. In my application there is only one window enabled at a time and I want to improve the usability. If the user clicks on the wrong (disabled) main window the application should auto focus to the enabled window.
I know that disabled means that the window does not respond to any event, but is there a solution like a global event handler or some special WPF event?
I tried a PreviewMouseLeftButtonDown event but that did not work.
// event called from some special/ global event on disabled window
private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(App.Current.Windows.Count > 1)
{
foreach(Window w in App.Current.Windows)
{
if(w.IsEnabled)
{
w.Focus();
break;
}
}
}
}
Thanks for your ideas/solutions!
Calling ShowDialog means you want to make window being showed modal, which disables other windows.
Switch this method to Show and you'll be able to use other windows as well.
Refer to this.
Thanks for the hint but as a requirement I've to ensure that the main window is freezed when another window is opened and I've found a solution: Instead of freezing the window with .ShowDialog() I've freezed all controls when a new window is opened with .Show().
private void DisableAllControls()
{
// parallel execution cause of many elements
Parallel.For(0, VisualTreeHelper.GetChildrenCount(this), index =>
{
(VisualTreeHelper.GetChild(this, index)
as UIElement).IsEnabled = false;
});
}
I also added a MouseDownEvent to get focus an the new window if the user clicks on the "freezed" main window. (There will be only one additional window open at the same time).
private void FocusLastOpen_MouseDown(object sender, MouseEventArgs e)
{
if (App.Current.Windows.Count > 1)
{
foreach (Window w in App.Current.Windows)
{
if (w.IsEnabled && w.GetType() != typeof(MainWindow))
{
w.Focus();
}
}
}
}
To reactivate the elements of the main window when the other window has closed I've written a static method which will be executed on the ClosingEvent.
public static void EnableAllControls()
{
MainWindow obj = null;
foreach(Window w in App.Current.Windows)
{
if(w.GetType() == typeof(MainWindow))
{
obj = w as MainWindow;
break;
}
}
if(obj == null) return;
Parallel.For(0, VisualTreeHelper.GetChildrenCount(obj), index =>
{
(VisualTreeHelper.GetChild(obj, index)
as UIElement).IsEnabled = true;
});
}
Related
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;
I am starting XAML coding and cannot for the life of it find out if a window is openen or not (once openen by clicking a button)
For now, it keeps opening unlimited amounts of windows. What I want is that once a window is openen, it won't open again, even if you press the button again.
here's my code, but with this it's not showing a window at all!
What am i doing wrong?
private void System_Agents(object sender, RoutedEventArgs e)
{
var newW = new SystemAgents();
if ( newW == null )
{
newW.Show();
}
else newW.Activate();
When you create the window the first time, store the newly-created window instance in a member variable of the class that creates it. Then check that member variable before creating it the next time you want that window, and if it's not null, don't create another.
I solved it! After long searching, it was actually quite easy!
Here's the code:
SystemAgents window; //Presets a variable to SystemAgents window
private void System_Agents(object sender, RoutedEventArgs e) //Call method
{
if ( window == null )
{
window = new SystemAgents(); //Sets variable "window" to the window "SystemAgents"
window.Show(); //Shows the window "System Agents"
window.Owner = this; //Determins the owner of the window is the main Application
window.Closed += new EventHandler(AddItemView_Closed); //Sets a new method (defined below) to what happens if you close the window so window will close when app closes.
}
else window.Activate(); //Will set the window as active.
//newW.ShowDialog(); //Will Show Window, but unable to do anything else other then the window
}
void AddItemView_Closed(object sender, EventArgs e)
{
window = null;
}
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();
}
// ...
I have a wpf project which has couple of windows, whne i navigate from one window to other i just hide one window and create instance of other if not created already, otherwise just make it visible
in all windows there is window closing event handler
private void Window_Closing_1(object sender, CancelEventArgs e)
{
{
string message = "You are trying to close window " + this.Name + " .Are you sure?";
string caption = "Exit";
MessageBoxButton buttons = MessageBoxButton.YesNo;
MessageBoxImage icon = MessageBoxImage.Question;
if (MessageBox.Show(message, caption, buttons, icon) == MessageBoxResult.Yes)
{
App.Current.Shutdown();
}
else
{
MessageBox.Show("Closing aborted");
}
}
but problem is this event is there in every window so when i close it lots of other prompt from other window which are invisible also show up. Is there a way to avoid other pronpts if i close in only one window?
Have you tried in App.xaml to add Exit attibute?
it will be a better solution since you will only have to write this confirmation exit code just once. about window name you could cast sender to window in order to find out its name
just create a static method in another class to handle closing of forms.
public class X
{
private static bool isClosingHandled = false;
public static void HandleClose()
{
//// app closing logic
isClosingHandled = true;
}
}
private void Window_Closing_1(object sender, CancelEventArgs e)
{
X.HandleClose();
}
I am using visual studio 2010 to do my C# GUI.
The current problem that I am facing is that after maximizing a window, it stays there but when I go to other forms, the window will go back to its original size.
How do I leave the maximized window all the way for all the forms, once I click the maximize button?
Heres an example:
User maximizes Form A
Form A maximized
User goes to Form B
Form B goes back to original size instead of a maximized window
What I want is when user maximizes a form, it stays that way till the program is closed or resized.
Assuming you're using WinForms, you can have either implement a shared FormWindowState manager or use a Multiple Document Interface (MDI) container.
Shared FormWindowState
You can register each of your forms with a class responsible for propagating changes in forms' FormWindowState.
public class FormWindowStateManager {
List<Form> _Forms;
...
public void Register(Form form) {
if(!_Forms.Contains(form)) {
_Forms.Add(form);
form.Resize += new EventHandler(Form_Resize);
}
}
public void Unregister(Form form) {
if(_Forms.Contains(form)) {
_Forms.Remove(form);
form.Resize -= new EventHandler(Form_Resize);
}
}
private void Form_Resize(object sender, EventArgs e) {
Form form = sender as Form;
if(form != null) {
if(form.FormWindowState == FormWindowState.Maximized || form.FormWindowState == FormWindowState.Normal) {
PropagateWindowState(form.FormWindowState);
}
}
}
private void PropagateWindowState(FormWindowState state) {
foreach(Form form in _Forms) {
if(form.FormWindowState != state) {
form.FormWindowState = state;
}
}
}
}
MDI Container
MdiParentForm.cs
IsMdiContainer = true;
MdiChildForm.cs
MdiParent = myParentForm; // instance of MdiParentForm
You can iterate through a form's MDI children using the form's MdiChildren property such that when on MDI child window changes its FormWindowState, the MDI parent form can apply the change to each of its children, similar to the shared FormWindowState approach.
These ideas are just off the top of my head but maybe they'll get you in the right direction.