Implementing UIA provider for TextBox and MaskedTextBox controls#7741
Conversation
a97f295 to
f1276a6
Compare
vladimir-krestov
left a comment
There was a problem hiding this comment.
Looks good, but should be carefully tested
...rms/PropertyGridInternal/PropertyGridView.GridViewTextBox.GridViewTextBoxAccessibleObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.TextBoxBaseAccessibleObject.cs
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.TextBoxBaseAccessibleObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/UpDownBase.UpDownEdit.cs
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/UpDownBase.UpDownEdit.cs
Show resolved
Hide resolved
...ystem.Windows.Forms/tests/UnitTests/System/Windows/Forms/TextBoxBaseAccessibleObjectTests.cs
Show resolved
Hide resolved
...ystem.Windows.Forms/tests/UnitTests/System/Windows/Forms/TextBoxBaseAccessibleObjectTests.cs
Outdated
Show resolved
Hide resolved
...ests/UnitTests/System/Windows/Forms/UpDownBase.UpDownEdit.UpDownEditAccessibleObjectTests.cs
Outdated
Show resolved
Hide resolved
f1276a6 to
efaa031
Compare
dmitrii-drobotov
left a comment
There was a problem hiding this comment.
Nice work! Did you also test that there are no memory leaks for accessible objects after your changes?
src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.cs
Outdated
Show resolved
Hide resolved
| if (@object is TextBoxBaseAccessibleObject accessibleObject) | ||
| { | ||
| accessibleObject.ClearObjects(); | ||
| } |
There was a problem hiding this comment.
The first case was removed because of
UiaCore.UiaDisconnectProvideris called from another place.
It's called only when control has SupportsUiaProviders as true, but there is RichTextBox for which it's false. I'm not sure about all the details here, but RichTextBox could still somehow have an active AccessibilityObject for which we need to call UiaCore.UiaDisconnectProvider.
12bc14f to
661b73e
Compare
Tanya-Solyanik
left a comment
There was a problem hiding this comment.
Looks good, I added some comments, please see them. Had you compared the resulting provider set and properties to what is required by the docs https://docs.microsoft.com/windows/win32/winauto/uiauto-supporteditcontroltype?
| => Owner is TextBoxBase textBoxBase && textBoxBase.ReadOnly; | ||
| => Owner is TextBoxBase { ReadOnly: true }; | ||
|
|
||
| public override string? Name => Owner.AccessibleName ?? string.Empty; |
There was a problem hiding this comment.
Why does the base class implementation not work? TextBox should get AccessibleName from the label placed before it in the tab order. You dropped that part of the implementation. Maybe it does not make sense for the DGV cells, but it makes sense for other TextBoxes.
There was a problem hiding this comment.
When I compared my implementation with MSAA behavior, the AccessibleName was empty. It was a reason why I implemented it that way. It was probably wrong and I've reworked it through the documentation above.
There was a problem hiding this comment.
I see that now accessible names match the TextBox content:

I don't think this is expected behavior because it makes Narrator announce the content twice:
TextBoxes window, Some long long text for a multiline TextBox that contains several lines with withspaces,tabs and numbers 12345, edit, Some long long text for a multiline TextBox that contains several lines with withspaces,tabs and numbers 12345,
Some long long text for a RTL TextBox, edit, Some long long text for a RTL TextBox,
Some long long text for a TextBox, edit, Some long long text for a TextBox,
If there is a label before TextBox then name will be filled from it — this functionality now works, but the default name should be empty. Also, check docs:
UIA_NamePropertyId — The name of the edit control is typically generated from a static text label. If there is not a static text label, a property value for Name must be assigned by the application developer. The Name property should never contain the textual contents of the edit control.
There was a problem hiding this comment.
I see this as an application problem that should be raised by the AccessibilityInsights for the app developer to fix. Framework does not know the business logic behind this text box and can't assign a meaningful name. As long as tooling raises the issue, we are good.
If there is a code path to keep Accessible Name empty , it would be a better fix, but I wouldn't spend much time on it (I think we have a property that controls it)
src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.TextBoxBaseAccessibleObject.cs
Show resolved
Hide resolved
...m.Windows.Forms/src/System/Windows/Forms/UpDownBase.UpDownEdit.UpDownEditAccessibleObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/ToolStripTests.Designer.cs
Show resolved
Hide resolved
661b73e to
ed69ba3
Compare
ed69ba3 to
05e9131
Compare
Tanya-Solyanik
left a comment
There was a problem hiding this comment.
Please see the question about the RichTextBox
src/System.Windows.Forms/src/System/Windows/Forms/DataGridViewTextBoxEditingControl.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/UpDownBase.UpDownEdit.cs
Show resolved
Hide resolved
...ystem.Windows.Forms/tests/UnitTests/System/Windows/Forms/TextBoxBaseAccessibleObjectTests.cs
Show resolved
Hide resolved
...ystem.Windows.Forms/tests/UnitTests/System/Windows/Forms/TextBoxBaseAccessibleObjectTests.cs
Show resolved
Hide resolved
05e9131 to
cc2a609
Compare
dmitrii-drobotov
left a comment
There was a problem hiding this comment.
Looks good! I also checked the accessibility docs for edit control and found some inconsistencies. For example:
If an edit control contains placeholder text (for example, a cue banner), the text should be used as the HelpText property unless the text can be edited by the user and then reused as placeholder text. For example, the Windows Internet Explorer address bar contains the text "about:Tabs" when a new tab is opened. This is not HelpText because it is a programmatic address that can be used or edited by the user.
We have the PlaceholderText property, so it's possible to set a placeholder, but the HelpText property won't be set, because it's not implemented in this PR. But what I found is that this functionality didn't work before, so this PR won't be a regression.
I didn't go through all the docs content but there is at least UIA_IsPasswordPropertyId with the same problem — it's not implemented in this PR but wasn't working before either. Should we fix all these inconsistencies in this PR or later as separate issues?
|
@dmitrii-drobotov - great findings! Yes, please open a new issue. |
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
Tanya-Solyanik
left a comment
There was a problem hiding this comment.
Thank you! Please sent to the CTI team for testing if you had not done already.
1f003dd
1f003dd to
ead1356
Compare
|
Fixed cases that CTI found. |
src/System.Windows.Forms/src/System/Windows/Forms/TextBoxBase.TextBoxBaseAccessibleObject.cs
Outdated
Show resolved
Hide resolved
ead1356 to
067de2e
Compare
067de2e to
230b77f
Compare
src/System.Windows.Forms/src/System/Windows/Forms/MaskedTextBox.cs
Outdated
Show resolved
Hide resolved
...rms/tests/UnitTests/System/Windows/Forms/MaskedTextBox.MaskedTextBoxAccessibleObjectTests.cs
Show resolved
Hide resolved
230b77f to
cfe49c2
Compare
…net#7741) Enabled UIA provider for TextBox with nested classes and MaskedTextBox. Refactored TextBox's child classes to reduce extra code. Implemented IValueProvider for TextBoxBaseAccessibleObject. Raised AutomationFocusChangedEvent in OnGotFocus methods. Added few unit tests.




Fixes #3421
Proposed changes
TextBoxwith nested classes andMaskedTextBox.TextBox'schild classes to reduce extra code.IValueProviderforTextBoxBaseAccessibleObject.AutomationFocusChangedEventinOnGotFocusmethods.Customer Impact
TextBoxwith nested classes andMaskedTextBoxcontrol accessibility.Regression?
Risk
Screenshots
Before
TextBox
MaskedTextBox
After
TextBox
MaskedTextBox
Test methodology
Accessibility testing
Test environment(s)
Microsoft Reviewers: Open in CodeFlow