I have a window in which I handle the Closing event in a custom function. In the XAML I have set the following:
<ext:ExtendedWindow x:Name="Window1" Closing="Window_Closing">
This function is declared in the code-behind as follows:
private void Window_Closing(object sender, CancelEventArgs e)
{
Closing -= Window_Closing;
e.Cancel = true;
Storyboard storyboard = this.CloseWindowWidthAnimation(0f);
storyboard.Completed += CloseWindow;
storyboard.Begin();
}
private void CloseWindow(object sender, EventArgs e)
{
this.Close();
}
Window_Closing cancels the closing event and plays an animation on the window (width shrinks to 0). To the Completed event I add a function that finally closes the window after the animation has played. CloseWindowWidthAnimation is a static method in a helper class that just returns a storyboard. The ExtendedWindow has a base class of Window and only has a few dependencyproperties to handle color schemes.
When the Close function is done executing and Just My Code is enabled, the 'break mode' screen pops up. Continuing the debugging session exits the application, but I think this is a known issue. When Just My Code is disabled, the following error shows:
This Visual is not connected to a PresentationSource.
The error shows when the window has in fact been closed after CloseWindow exits. I do think it has something to do with the storyboard/animation, since it does not throw the error when I don't override the Closing event. When I build the app and run the executable, it doesn't crash and I don't catch the error somewhere. I'm thinking it has something to do with the storyboard, but the error isn't very descriptive and I haven't been able to find anything on this. So my question is as follows:
What might cause this type of behaviour? What could I possibly do to fix this?
Update: Call Stack window (Main thread)
Related
I have created a WPF application, that is designed to run in the background and uses an icon in the system tray.
To achieve this goal, I have attached the following method to the Closing event of the MainWindow otherwise it closes. Also to note in the App.xaml I have set the ShutdownMode to OnExplicitShutdown
private void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
//This method simply displays a notification to the user that the app is still running in the system tray.
DisplaySysTrayNotification();
}
The problem I am facing is that on the Context Menu of the System Tray Icon I have an Exit button which calls
App.Current.Shutdown();
This causes the Closing event to fire again and display the notification, which I do not want to do. How can I prevent this event firing again?
Or is this not possible and will I have to use a boolean variable called ShuttingDown to handle it and check this variable before displaying the notification?
on window closing, the app can either be actually just fine (clicking X on the window), or really force closing (from the context menu).
one way to do this is the way you're looking for, essentially "when the context menu is clicked to 'force close' the app, remove the window event handler before calling App.Current.Shutdown()".
private void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
//This method simply displays a notification to the user that the app is still running in the system tray.
DisplaySysTrayNotification();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MainWindow.Closing -= Window_Closing;
App.Current.Shutdown();
}
another way to do this is to track if we're force closing the app, essentially "when the context menu is clicked to 'force close' the app, set a 'force close' flag to true so that the window knows we're actually closing for real and to not do the minimizing stuff."
this means there should be a flag in scope of both the window and the context menu. this flag would be initialized as false, considering that there will only ever be 1 force close, which will be when the app ends.
i'll call the flag _IsForceClosing. it's naturally initialized to false.
bool _IsForceClosing;
private void Window_Closing(object sender, CancelEventArgs e)
{
if (_IsForceClosing)
return; //don't do the hiding stuff, we're really closing
e.Cancel = true;
this.Hide();
//This method simply displays a notification to the user that the app is still running in the system tray.
DisplaySysTrayNotification();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
_IsForceClosing = true;
App.Current.Shutdown();
}
I have a strange issue overriding BackkeyPress Function in code behind, inside the function i have a simple message box to Go back or cancel navigation ( stay in current page ), when no choice is made (ok or cancel ) and Messagebox is open for long time, Application crashes, when i try to debug, no exception is thrown and App remains in the state unless OK or cancel is pressed , but on Normal run ( without debugger ) the crash is apparent.
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
string caption = "exit?";
string message = "Do you still want to exit?";
e.Cancel = MessageBoxResult.Cancel == MessageBox.Show(message, caption,
MessageBoxButton.OKCancel);
base.OnBackKeyPress(e);
}
http://msdn.microsoft.com/en-US/library/windowsphone/develop/jj206947(v=vs.105).aspx
In Windows Phone 8, if you call Show in
OnBackKeyPress(CancelEventArgs) or a handler for the BackKeyPress
event, the app will exit.
You can work around this by calling Show on a different thread, as
described in the following steps. Override BackKeyPress or create a
handler for the BackKeyPress event. Set the Cancel to true to cancel
the back key press action. Dispatch a method that shows the
MessageBox. If the user chooses to leave the app, call Terminate(),
otherwise, do nothing.
I found one more solution to this, so I thought it would be good if I posted it here. It's just a workaround though.
private async void PhoneApplicationPage_BackKeyPress (object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
await Task.Delay(100);
if (MessageBox.Show(msg, cap, MessageBoxButton.OKCancel) == MssageBoxResult.OK)
{
//somecode
}
}
Source
When using Terminate() - be aware that a number of app.xaml.cs rootFrame navigating events associated with normal exit won't trigger, neither the ApplicationClosing or your page's OnNavigatedFrom. So check if anything going on is important. You might tack it on before terminating...
I am creating a window object globally and display it only when it is necessary, most of the time window will be in invisible mode. I have some work to do whenever the window is visible. can any one please tell me which message should i override to put the code which is supposed to execute when a window.show method is called?
IsVisibleChanged should do what you want.
private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue == true)
{
//Do what you need here
}
}
Look at the Window class documentation and also the Window lifetime cycle. Now out of this, we can conclude that you (probably) need the IsVisibleChanged event.
I want to hide my form while keeping my application running in background.
I've used notifyIcon and it remains always visible.
I've used "this.Hide();" to hide my form but unfortunately my application gets close (no exception).
I am also using threading and this form is on second thread.
Please tell me how can I solve it.
I am also using threading and this form is on second thread.
My crystal ball says that you've used ShowDialog() to show the form. Yes, calling Hide() on a modal dialog will close it. Necessarily so, a modal dialog normally disables all of the windows in the application. If you hide it then there's no way for the user to get back to the program, there are no windows left to activate. That this form runs on another thread otherwise doesn't factor into the behavior.
You'll need to call Application.Run(new SomeForm()) to avoid this. Now it isn't modal and you can hide it without trouble. But really, do avoid showing forms on non-UI threads. There's no reason for it, your main thread is already quite capable.
add the following event handlers for form resize and notify icon click event
private void Form_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
this.Hide();
}
}
private void notifyIcon_Click(object sender, EventArgs e)
{
this.Show();
this.WindowState = FormWindowState.Normal;
}
but this is not close you application
I have a form in a Windows form application that I want to display on top of a main form, close it, and then immediately show a dialog box using MessageBox.Show(). But the first form is still showing when the message box is shown, and it does not disappear until I click OK on the message box. I tried waiting to show the message box in an event handler for the form's VisibleChanged event and even calling Refresh() on both the form and the main form. Is there a way I can determine when the first form has fully disappeared before displaying the message box?
Edit:
Here is some code that demonstrates how the forms are being shown.
static class Program
{
// The main form is shown like this:
static void Main()
{
Application.Run(new MainForm());
}
}
public class Class1
{
// _modalForm is the first form that is displayed that won't fully go away
// when it is closed.
ModalForm _modalForm;
BackgroundWorker _worker;
public Class1()
{
_modalForm = new ModalForm();
_worker = new BackGroundWorker();
_worker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted
}
public void Method1()
{
_worker.RunWorkerAsync();
// The first form is shown.
_modalForm.ShowDialog();
}
// This code runs in the UI thread.
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_modalForm.VisibleChanged += new EventHandler(_modalForm_visibleChanged);
_modalForm.Close();
}
void _modalForm_visibleChanged(object sender, EventArgs e)
{
// When the message box is shown, the other form is still visible
// and remains so until I click OK.
MessageBox.Show("The other form was just closed.");
// Note: I originally tried to use the FormClosed event instead of
// VisibleChanged. Then I tried Deactivate, in attempt to use an event
// that occurred later thinking that might do the trick. VisibleChanged
// is the latest event that I found.
//
}
I'll guess that you are running your code on Windows XP or Vista/Win7 with Aero turned off. Closing a form does not make the pixels on the screen disappear instantly. The Windows window manager sees that the window for the form got destroyed and that this revealed parts of other windows underneath it. It will deliver a WM_PAINT message to let them know that they need to repaint the parts of the window that got revealed.
This will not work properly if one or more of those windows isn't actively pumping a message loop. They can't see the WM_PAINT message. They won't repaint themselves, the pixels of the closed form will remain on the screen.
Find out why these windows are not responding. Hopefully it is your window and the debugger can show you what the UI thread is doing. Make sure it isn't blocking on something or stuck in a loop.
After seeing the edit: there's indeed blocking going on, of a different kind. The MessageBox.Show() call is modal, it prevents the VisibleChanged event from completing. That delays the closing of the form.
Use System.Diagnostics.Debug.WriteLine() or Console.WriteLine() to get diagnostics in a Window Forms app. You'll see it in the Output window. Or simply use a debugger breakpoint.
The Form.FormClosed event is raised when the form completes closing. At this point, all Form.FormClosing event handlers have been run, and none of them canceled the close.
Form.FormClosed replaced Form.Closed (which is deprecated) in the .NET 2.0 framework.
Form.Closed Event
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.closed(VS.71).aspx