-
Notifications
You must be signed in to change notification settings - Fork 991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #12661 Null Reference Exception: System.Windows.Forms.TabControl.<WmSelChange> #12683
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5703,6 +5703,30 @@ public void TabControl_Invokes_SetToolTip_IfExternalToolTipIsSet() | |
Assert.Equal(text, actual); | ||
} | ||
|
||
[WinFormsFact] | ||
public void TabControl_WmSelChange_SelectedTabIsNull_DoesNotThrowException() | ||
{ | ||
using Form form = new(); | ||
using TabControl control = new(); | ||
using TabPage page1 = new("text1"); | ||
using TabPage page2 = new("text2"); | ||
control.TabPages.Add(page1); | ||
control.TabPages.Add(page2); | ||
_ = control.AccessibilityObject; | ||
|
||
form.Controls.Add(control); | ||
form.Show(); | ||
|
||
control.SelectedIndex = 1; | ||
control.TabPages.Clear(); | ||
|
||
Action act = () => control.TestAccessor().Dynamic.WmSelChange(); | ||
Application.DoEvents(); | ||
Thread.Sleep(1000); | ||
John-Qiao marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
act.Should().NotThrow(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this scenario, exception happens after WmSelChange had been executed, the delegate is only scheduled for execution with BeginInvoke.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So here we need to ensure that SelectedTab is diaposed after
|
||
} | ||
|
||
private class SubTabPage : TabPage | ||
{ | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also test
if (IsAccessibilityObjectCreated && SelectedTab?.ParentInternal is TabControl)
inside the method invoker delegate in case the control had been disposed before the delegate was invoked.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the
BeginInvoke
delegate, should we consider adding conditional checks forIsAccessibilityObjectCreated
andSelectedTab?.ParentInternal is TabControl
to ensure the state is valid at execution time?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is
SelectedTab.IsDisposed
possible? Please double-check if we are un-selecting tabs before disposing them.It's ok to create accessibility object for a non-disposed child control, if the parent has an accessible object. The child accessible object will be created to support some other user action anyway if accessibility tools are being used. And we know that accessibility tools are used because they initiated creation of the parent accessible object.