views:

388

answers:

1

This is a C#, Winform question.

I have a TabControl control and I use two navigation buttons to switch among my tab pages. I used TabControl.SelectedIndex = i to change the showing tab pages in the buttons' click event. Every time a specific tab page is going to be shown, one of several functions is called to prepare some background work. The calls to the functions are put to TabControl.SelectedIndexChanged event.

I came across a problem. If an exception is thrown from TabControl.SelectedIndexChanged event (from one of the several functions get called in that event), I no longer can use the programmatic way to switch among tab pages. Once one exception is thrown, the navigation buttons cannot change the showing tab of the TabControl. Be more specifically, the SelectedIndex of TabControl still can be changed, the tabs UI still changes but the tab page content remains the same as the page that having exception thrown out.

Anyone came across this problem before? Any solution? Many thanks.

+2  A: 

As a general rule, exceptions in WinForms event handlers should be caught and handled. If the exception is allowed to go up the stack into the WinForms code, strange behavior - like what you're experiencing - is a common result.

Using Reflector to look at System.Windows.Forms.TabControl, its WndProc() method calls WmSelChange(), which calls your event handler. When an exception occurs in the event handler, the exception percolates up the stack to WndProc. WndProc doesn't handle the exception, so this if/then statement at the end of WndProc never gets called:

if (m.Msg == this.tabBaseReLayoutMessage)
{
    this.WmTabBaseReLayout(ref m);
}
else
{
    base.WndProc(ref m);
}

Therefore the tab control's internal state is corrupted, resulting in the odd behavior.

To cleanly handle exceptions that might occur during a tab change, I suggest using the Selecting event to perform the background work (this event gets fired before the SelectedIndexChanged event). Use a try/catch statement, and in the catch clause set TabControlCancelEventArgs.Cancel to true to cancel the tab change.

Chris R. Timmons
Many thanks to the solution. That is helpful.
Steve