I find when an exception occurs in MainWindow#Window_Closing method, even I set the e.cancel = true before the exception and e.handled = true in App#DispatcherUnhandledException, the application still shutdown.
I set a breakpoint in Application_Exit method and the stacktrace shows the shutdown is called by ExceptionWrapper.InternalRealCall -> Application.ShutdownCallback -> Application.ShutdownImpl -> Application.DoShutdown
Could anybody help me understand why this happens and is there any way to avoid application shutdown when exception happens in Window_Closing method? (I know I can always catch all exception in this method but I'd like to know if there is any better approach to avoid unexpected exception kill the application)
Below is sample code to reproduce this issue. Click the window close button to reproduce this issue.
Thanks.
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
throw new Exception();
}
}
App.xaml.cs
public partial class App : Application
{
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
}
private void Application_Exit(object sender, ExitEventArgs e)
{
var exitCode = e.ApplicationExitCode;
}
}
App.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
StartupUri="MainWindow.xaml" DispatcherUnhandledException="Application_DispatcherUnhandledException" Exit="Application_Exit">
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Closing="Window_Closing">
It's fine catching the DispatcherUnhandledException, but that's not the end of it. If you catch it and set Handled to true, then the application just says OK, and shuts down. If Handled is set false, it says 'Still needs a bit of a check' and then if the AppDomain UnhandledException is set it calls that:
In your App.xaml.cs file:
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = false;
}
private void Application_Startup(object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(string.Format("Is Terminating: {0}\r\n{1}", e.IsTerminating, e.ExceptionObject.ToString()));
}
Here the CurrentDomain_UnhandledException method is only called is I set Handled to false. Either way, the apps going down.
Note that UnhandledExceptionEventArgs doesn't have a Handled property, but it does have an IsTerminating one. I'm not sure under what circumstances that would be false, though.
EDIT - Turns out that IsTerminating will only be false when compatibility is set to .NET 1.0 and 1.1 as in those versions of the framework an unhandled exception in some background threads would not cause the app to close. Since 2.0, all unhandled exceptions will cause the app to close.
If you look at the WPF source, you will see that this is by design. There is even an explicit comment to that effect:
// Event handler exception continuality: if exception occurs in Closing event handler, the
// cleanup action is to finish closing.
CancelEventArgs e = new CancelEventArgs(false);
try
{
OnClosing(e);
}
catch
{
CloseWindowBeforeShow();
throw;
}
I guess it makes sense, since you wouldn't want a bug to prevent the user closing a window.
I came across this few days back during one of my WPF projects. Yes, it is possible to prevent the application from shutting down on unhandled exceptions. Just let the application know that the exception is handled so that the application does not take additional actions. Makes sense right?
Wherever you initialize the application or have access to the Application Instance, add an event 'DispatcherUnhandledException' to the object of the instance. You will preferably have to add the event invoke function to App.xaml.cs of your WPF project.
Add this to the Constructor of App.
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
Then add the Current_DispatcherUnhandledException function within the same class.
public static void Current_DispatcherUnhandledException (object sender, DispatcherUnhandledExceptionEventArgs e)
{
var errorBox = new Core.Common.UI.WPF.MessageBox();
errorBox.Error(e.Exception.Message);
//Log to Database
var logger = Logger.NLogger.GetLogger("My-Logger");
logger.Error(e.Exception, e.Exception.Message);
e.Handled = true;
}
You could also Log the exceptions externally to DB, File System.
e.Handled = true; This line tells the application that the exception is handled and not to worry about it.
PRO TIP - Make sure no exceptions happen within the DispatcherHandledException, else the Application will still close down.
Related
I have a fairly simple C# WPF application using .NET 5. Basically it sits in the background and times specific events for the end user. The events are built from a xml file that is generated externally.
The application consists of 2 windows, one hidden that does all the thinking. If it detects that an event is due it raises a toast message which when clicked on opens the other window to show the event details to the user. All works fine and runs as expected except after a windows sleep/suspend and resume. We obviously don't want the events to add up upon sleep/suspend and so we close the hidden window and upon resume open it again. No problems there but once the system is resumed and an event is raised the visible window refuses to show. If the visible window is open when sleep/suspend happens then upon resume the whole window is frozen and refuses to respond (only way to close the window is kill the application and restart)
The APP code is as follows :-
public static Forms.NotifyIcon notifyIcon;
public static MainWindow mw;
public static ConfigWindow cw;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
// Listen to notification activation
ToastNotificationManagerCompat.OnActivated += toastArgs =>
{
// Obtain the arguments from the notification
ToastArguments args = ToastArguments.Parse(toastArgs.Argument);
// Obtain any user input (text boxes, menu selections) from the notification
ValueSet userInput = toastArgs.UserInput;
// Need to dispatch to UI thread if performing UI operations
Application.Current.Dispatcher.Invoke(delegate
{
ToastControl.HandleToast(args);
});
};
ConfNotifyIcon();
OpenApp();
}
private void ConfNotifyIcon()
{
notifyIcon = new Forms.NotifyIcon();
notifyIcon.Icon = new System.Drawing.Icon("Images/Wellformation.ico");
notifyIcon.DoubleClick += OnClick;
notifyIcon.ContextMenuStrip = new Forms.ContextMenuStrip();
notifyIcon.ContextMenuStrip.Items.Add("Open", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnClick);
notifyIcon.ContextMenuStrip.Items.Add("Close", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnClose);
notifyIcon.ContextMenuStrip.Items.Add(new Forms.ToolStripSeparator());
notifyIcon.ContextMenuStrip.Items.Add("Exit", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnExit);
}
private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
case PowerModes.Suspend:
this.Dispatcher.BeginInvoke((Action)(() =>
{
PrepareLock();
}), null);
break;
case PowerModes.Resume:
this.Dispatcher.BeginInvoke((Action)(() =>
{
PrepareAwake();
}), null);
break;
default:
break;
}
}
private void PrepareAwake()
{
OpenApp();
ConfNotifyIcon();
notifyIcon.Visible = true;
}
private void PrepareLock()
{
notifyIcon.Dispose();
cw.Close();
}
private void OnExit(object sender, EventArgs e)
{
Application.Current.Shutdown();
}
private void OnClose(object sender, EventArgs e)
{
mw.Close();
}
private void OnClick(object sender, EventArgs e)
{
OpenMain();
}
private void OpenMain()
{
mw = new();
mw.Show();
mw.Activate();
}
public static void OpenApp()
{
cw = new ConfigWindow();
}
The hidden Window XAML is as follows :-
<Window x:Class="WellformationDesktopApplication.ConfigWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WellformationDesktopApplication"
mc:Ignorable="d"
Title="ConfigWindow" Height="1" Width="1" Visibility="Hidden" WindowState="Minimized">
<Grid>
</Grid>
</Window>
with code as follows :-
Timer at = new();
public ConfigWindow()
{
BuildConfig();
InitializeComponent();
}
public void refreshconfig()
{
myObjects.Clear();
myObjects = NudgeManager.GetNudges();
NudgeHandler(myObjects);
}
public void BuildConfig()
{
myObjects.Clear();
myObjects = GetEvents(); // pulls a list of event names with intervals from the config file
EventHandler(myObjects); //Goes through the list of events and figures out when the next event is due based upon the interval in the configuration
ActionTimer();
}
private void ActionTimer()
{
at.Interval = 60000;
at.Elapsed += ChecktActions;
at.AutoReset = true;
at.Enabled = true;
}
private void ChecktActions(object sender, ElapsedEventArgs e)
{
//Go through the trigger times for all events and see if those time have passed, if they have raise a toast showing the event name.
//If an event is raised reset the trigger time for the event based upon the interval and reset that time.
}
and the visible window XAML is as follows :-
<Window x:Class="WellformationDesktopApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WellformationDesktopApplication"
mc:Ignorable="d"
ResizeMode="NoResize"
WindowStyle="None"
Title="MainWindow" Height="500" Width="800" Background="{x:Null}" Foreground="{x:Null}" AllowsTransparency="True">
<Grid x:Name="BG">
<TextBlock x:Name="Display" HorizontalAlignment="Left" Margin="546,13,0,0" Text="Show event name and appropriate information about the event here..." VerticalAlignment="Top" FontSize="22"/>
</Grid>
</Window>
With Code as follows :-
public MainWindow()
{
InitializeComponent();
setstyles();
this.MouseLeftButtonDown += delegate { DragMove(); };
}
We know that everything to do with the ConfigWindow works fine, we know it is closed upon suspend and a new one is opened on resume with new timings set and all the appropriate alerts working.
The issue is with MainWindow as after a suspend and resume it cannot be interacted with at all. The open button on the icon does nothing, if the window is opened is is completely frozen and cannot be interacted with in any way, and if a toast is clicked on the window does not open but the rest of the toast handling code works fine around it. This happens on Win8, Win10 and Win11.
Any help out there as I am completely at a loss for how this is happening?
Thanks
After much work and going through the code section by section commenting it out to see if it made a difference I have found the issue.
Buried deep inside the the code for the hidden window (4 calls to functions down the line) I found that the EventHandler() was also raising a listener for
SystemEvents.SessionSwitch += new SessionSwitchEventHandler(OnSessionSwitch);
With all the associated functions buried in a separate class that was not directly referenced from the window itself.
When this line was commented out everything worked fine, with it in and attached to the hidden window after Suspend/Resume of windows no UI changes would take place throughout the whole code (hence hidden window continued to working completely fine as it did not interact with the UI).
By lifting this code out into the APP space and handling it there rather than in a window the problem has gone away (though has revealed other issues that were not being handled upon Resume of Windows that I now have to fix).
So the answer is that for a WPF application listeners for SystemEvents of any type need to be housed int the APP code space and not within windows.
We've been using unhandled exceptions for ages and we register both Application.Current.DispatcherUnhandledException and AppDomain.CurrentDomain.UnhandledException
but the following repro case using Drop Event handler does not trigger any unhandled exception handler.
When I throw the exception from UI or task, some handler will be triggered, but form the documentation I don't comprehend why no handler is triggered in my scenario below as I would expect the Dispatcher calling DispatcherUnhandledException
This is VS 2015 with .net 4.5.2
Repro WPF code is very simple, only AllowDrop and Drop handler. Note: The handlers are registered in the window ctor, same behaviour when doing that in app.xaml.cs.
Just drag & drop any file into it, a message box should appear but it does not.
<Window x:Class="unhandledex_wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" AllowDrop="True" Drop="MainWindow_OnDrop">
<Grid>
</Grid>
</Window>
Code behind:
using System;using System.Threading.Tasks;using System.Windows;
namespace unhandledex_wpf
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Application.Current.DispatcherUnhandledException += ( sender, args ) => MessageBox.Show( "Exception" );
AppDomain.CurrentDomain.UnhandledException += ( sender, args ) => MessageBox.Show( "Exception" );
TaskScheduler.UnobservedTaskException += ( sender, args ) => MessageBox.Show( "Exception" );
// works Task.Run( ( )=> { throw new Exception( "foo" ); } );
}
private void MainWindow_OnDrop( object sender, DragEventArgs e )
{
throw new NotImplementedException("Catch me");
}
}
}
If you want to handle an exception during a drop event you must handle it within your Drop event handler. Please refer to Peter Ritchie's answer in the following thread on the MSDN forums for more information about why: https://social.msdn.microsoft.com/Forums/windows/en-US/8beb1aba-1699-46c7-84dc-38768c7a21f6/treeview-dragdrop-event-ignores-exceptions-help?forum=winforms
Jay Wang (MSFT) has confirmed this in the WPF forum: https://social.msdn.microsoft.com/Forums/vstudio/en-US/a336acc8-5a29-45aa-b84a-8e235a0f838a/wpf-drop-event-hides-thrown-error?forum=wpf
There are many questions on SO asking same doubt.
Solution for this is to set
notifyIcon.icon = null and calling Dispose for it in FormClosing event.
In my application, there is no such form but has Notification icon which updates on Events.
On creation, I hide my form and make ShowInTaskbar property false. Hence I can not have a "FormClosing" or "FormClosed" events.
If this application gets event to exit, It calls Process.GetCurrentProcess().Kill(); to exit.
I have added notifyIcon.icon = null as well as Dispose before killing, but still icon remains taskbar until I hover mouse over it.
EDIT: If I assume that this behaviour is due to calling GetCurrentProcess().Kill(), Is there any elegant way to exit from application which will clear all resources and remove icon from system tray.
You can either set
notifyIcon1.Visible = false;
OR
notifyIcon.Icon = null;
in the form closing event.
The only solution that worked for me was to use the Closed event and hide and dispose of the icon.
icon.BalloonTipClosed += (sender, e) => {
var thisIcon = (NotifyIcon)sender;
thisIcon.Visible = false;
thisIcon.Dispose();
};
Components just must be disposed in the right order like this :
NotifyIcon.Icon.Dispose();
NotifyIcon.Dispose();
Add this to the MainWindow closing event.
Hope this will help.
Use this code when you want to do it when you press the Exit or Close button:
private void ExitButton_Click(object sender, EventArgs e)
{
notifyIcon.Dispose();
Application.Exit(); // or this.Close();
}
Use this code when you want to do it when the form is closing:
private void Form1_FormClosing(object sender, EventArgs e)
{
notifyIcon.Dispose();
Application.Exit(); // or this.Close();
}
The important code is this:
notifyIcon.Dispose();
Use notifyIcon.Visible = False in FormClosing event
This is normal behaviour, unfortunately; it's due to the way Windows works. You can'r really do anything about it.
See Issue with NotifyIcon not dissappearing on Winforms App for some suggestions, but none of them ever worked for me.
Also see Notify Icon stays in System Tray on Application Close
Microsoft have marked this as "won't fix" on Microsoft Connect.
The only way that works to me was:
On design screen changing notifyicon1 property visible=false
Insert the code below on main form "activated" event:
NotifyIcon1.Visible = True
Insert the code below on main form "closing" event:
NotifyIcon1.Visible = false
NotifyIcon1.Icon.Dispose()
NotifyIcon1.Dispose()
I don't think WPF has it's own NotifyIcon, does it? If you're using the 3rd party Harcodet.Wpf.TaskbarNotification, then try this:
In order to prevent my app from closing when the window is closed (run in background), I separated the logic for closing the window (hitting the x button in the upper right) and actually shutting it down (through the context menu). To make this work, make your context menu set _isExplicitClose to true. Otherwise, it'll just hide the window and continue to run.
What this does is, on explicit close, hide tray icon and the form before closing. This way the icon isn't hanging around after the application is shutdown.
private bool _isExplicitClose;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (!_isExplicitClose)
{
e.Cancel = true;
Hide();
}
}
protected void QuitService(object sender, RoutedEventArgs e)
{
_isExplicitClose = true;
TaskbarIcon.Visibility = Visibility.Hidden;
Close();
}
Try Application.DoEvents(); after setting notifyIcon.Icon to null and disposing:
notifyIcon.Icon = null;
notifyIcon.Dispose();
Application.DoEvents();
And consider Environment.Exit(0); instead of Process.GetCurrentProcess().Kill().
i can tell you can solve the problem simply using the .dispose() method, but that is not called if you kill the process instead of exit the application.
please refer to Application.Exit if you have built a simple Windows Form application else refer to Environment.Exit that is more general.
I tried all of these and none of them worked for me. After thinking about it for a while I realized that the application creating the "balloon" was exiting before it had a chance to actually dispose of the balloon. I added a while loop just before Application.Exit() containing an Application.DoEvents() command. This allowed my NotifyIcon1_BalloonTipClosed to actually finish disposing of the icon before exiting.
while (notifyIcon1.Visible)
{
Application.DoEvents();
}
Application.Exit();
And the tip closed method: (You need to include the thisIcon.visible = false in order for this to work)
private void NotifyIcon1_BalloonTipClosed(object sender, EventArgs e)
{
var thisIcon = (NotifyIcon)sender;
thisIcon.Icon = null;
thisIcon.Visible = false;
thisIcon.Dispose();
}
I had the exact same problem as you.
The proper way are send WM_CLOSE message to a process.
I use the c# code I found in this article.
http://social.msdn.microsoft.com/Forums/vstudio/en-US/82992842-80eb-43c8-a9e6-0a6a1d19b00f/terminating-a-process-in-a-friendly-way
edit codes of ...Designer.cs as below coding.
protected override void Dispose(bool disposing)
{
if (disposing )
{
this.notifyicon.Dispose();
}
base.Dispose(disposing);
}
I couldn't make any one of the other solutions work. It turned out to be kind of a hybrid of all the above! I hunted and pecked until I had a consistently working solution both in debug and in EXE execution modes! I have no idea why MSFT would mark this as "Not going to fix"? I wish I had that liberty!
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
//THIS CODE IS CRAZY BUT MUST BE DONE IN ORDER TO PROPERLY REMOVE THE SYSTEM TRAY ICON!
//GREAT ARTICLE ON THIS ON STACK OVERFLOW
//https://stackoverflow.com/questions/14723843/notifyicon-remains-in-tray-even-after-application-closing-but-disappears-on-mous
//BTW THIS IS KIND OF A BLEND OF ALL THE SOLUTIONS BECAUSE I COULD NOT FIND A SINGLE SOLUTION THAT WOULD WORK!
systray_icon.Visible = false;
while (systray_icon.Visible)
{
Application.DoEvents();
}
systray_icon.Icon.Dispose();
systray_icon.Dispose();
Environment.Exit(1);
}
The right answer has already been given. But you must also provide a delay, for example with a timer. Only then the application can still remove the icon in the background.
private System.Windows.Forms.Timer mCloseAppTimer;
private void ExitButton_Click(object sender, EventArgs e)
{
notifyIcon.Visible = false; notifyIcon.Dispose;
mCloseAppTimer = new System.Windows.Forms.Timer();
mCloseAppTimer.Interval = 100;
mCloseAppTimer.Tick += new EventHandler(OnCloseAppTimerTick);
}
private void OnCloseAppTimerTick(object sender, EventArgs e)
{
Environment.Exit(0); // other exit codes are also possible
}
I am getting the following exception:
"Nullable object must have a value"
Everything was working when I was using
StartupURI="MainWindow.xaml"
but I wanted to implement a login screen so I changed this to
Startup="Application_Startup"
and then created the following method in App.xaml.cs:
private void Application_Startup(object sender, StartupEventArgs e)
{
UpdateAccounts();
bool result = true;
///*
LoginWindow login = new LoginWindow();
result = login.ShowDialog().Value;
/* */
if (!result)
{
return;
}
MainWindow window = new MainWindow();
bool main = window.ShowDialog().Value;
}
Does anyone have any idea what is going on? Or any suggestions on what is the best practice for implementing login interface.
The exception is being thrown at
bool main = window.ShowDialog().Value;
Exception Stack Trace:
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Nullable`1.get_Value()
My MainWindow.xaml was my default window that was being loaded when app started, and it worked prefectly fine. It has a lot of code inside it. A couple listboxes, a couple combo boxes, month calendar. It also connects to an access database.
To me it seems like my Window is return from ShowDialog() straight away, without letting me set DialogResult.
Update: I don't get an exception if i change my code to:
private void Application_Startup(object sender, StartupEventArgs e)
{
UpdateAccounts();
bool result = true;
///*
LoginWindow login = new LoginWindow();
result = login.ShowDialog().Value;
/* */
if (!result)
{
return;
}
MainWindow window = new MainWindow();
window.ShowDialog();
}
but I also don't get my main window show up, and the app just closes after logging in.
From the message that you receive it seems like your login.ShowDialog() is returning null.
Found a temporary fix, which isn't the best option but it works.
App.xaml:
<Application x:Class="Power_Scheduler.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup"
ShutdownMode="OnExplicitShutdown">
</Application>
Had to add ShutdownMode="OnExplicitShutdown"
in my code I used the Show() method rather than ShowDialog().
private void Application_Startup(object sender, StartupEventArgs e)
{
UpdateAccounts();
bool result = true;
///*
LoginWindow login = new LoginWindow();
result = login.ShowDialog().Value;
/* */
if (!result)
{
return;
}
MainWindow window = new MainWindow();
window.Show();
}
Which keeps the application running and shows the main window. And in the MainWindow, I subscribed to the Closed event and added the following code:
private void Window_Closed(object sender, EventArgs e)
{
Application.Current.Shutdown(0);
}
THanks for your help everyone,
I'm trying to figure out how when simply showing a WinForms dialog (code below) I get the following Exception and callstack. This doesn't happen all the time, but I'm seeing it in my exception logs. Any ideas? I can't figure out what would be referencing a disposed object?
I've verified (via the rest of the callstack) that the application is not shutting down, it is running normally.
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'MainForm'.
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Form.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.GetSafeHandle(IWin32Window window)
at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
at MyApp.MainForm.PromptForProfile()
at MyApp.MainForm.LoadProfile()
at MyApp.MainForm.barButtonItem1_ItemClick(Object sender, ItemClickEventArgs e)
This is the code for the dialog being displayed. The only "goofy" code is probably the textPassword_KeyDown handler. I should probably pull the code I want out and not call btnOK_Click that way.
public partial class ProfileForm : DevExpress.XtraEditors.XtraForm
{
public string _username;
public string _password;
public ProfileForm()
{
InitializeComponent();
}
private void btnOK_Click( object sender, EventArgs e )
{
_username = textUsername.Text;
_password = textPassword.Text;
}
private void textPassword_KeyDown( object sender, KeyEventArgs e )
{
if ( e.KeyCode == Keys.Enter )
{
btnOK_Click( sender, null );
this.DialogResult = DialogResult.OK;
e.Handled = true;
}
}
private void hyperLinkEdit1_Click( object sender, EventArgs e )
{
// show the proxy settings dialog
ProxyForm pform = new ProxyForm();
pform.ShowDialog();
}
}
Well, one possibilily is that you're setting DialogResult to Ok, which will close the form, but you then refer to the eventarg triggered by pressing Enter.
I'm not too sure of the role of the hyperlink edit1 bit, though. Is it on the same form, or a calling form?
Your stack trace tells me that you aren't getting into the ProfileForm code. It's failing on some control's CreateHandle. Without more information, I can only guess:
Verify that you're performing all your UI manipulation is occurring on your GUI thread. Even if you think it is, double check. (Sometimes the threading can be subtle.)
Make sure that you aren't trying to display the same form instance twice, the second time after it's already been disposed. I see that you've got a ShowDialog() happening, but if you're trying to ShowDialog() on a form that's already been disposed, I'd expect it to explode like this.
Ensure that any usercontrols on the form behave properly.
Consider using a secure string for your password field.