-
Notifications
You must be signed in to change notification settings - Fork 667
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
Screen reader does not read the heading of RadioButtons control #3183
Comments
@StephenLPeters @YuliKl as FYI. |
I'm no expert with the implementation of accessibility info so I don't assume I have the complete picture here. That said, I took a closer look at this. According to the documentation, headered controls typically would use the AutomationProperties.LabeledBy API to read out the (text-based) header when a control gets focus. The issue here seems to be that I did try to look into providing an own GetLabeledByCore implementation for the RadioButtons control here in the hope of working around this but I was not successful. An attempt which did prove to be successful here is to create a TextBlock in "code behind", establish the LabeledBy relation with it and set its // In RadioButtons::OnApplyTemplate()
if (const auto stackPanel = GetTemplateChildT<winrt::StackPanel>(L"RootPanel", controlProtected))
{
m_headerUIATextBlock = winrt::TextBlock();
winrt::AutomationProperties::SetLabeledBy(stackPanel, m_headerUIATextBlock);
UpdateHeader();
}
void RadioButtons::UpdateHeader()
{
if (m_headerUIATextBlock != nullptr)
{
m_headerUIATextBlock.Text(SharedHelpers::TryGetStringRepresentationFromObject(Header()));
}
}
void RadioButtons::OnPropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args)
{
winrt::IDependencyProperty property = args.Property();
if (property == s_HeaderProperty)
{
UpdateHeader();
}
// More properties left out here....
} While this works, I am not sure if that is a reasonable solution here. Controls like @ranjeshj @StephenLPeters FYI. (P.S.: Again, without me knowing the full picture, could |
The TextBox hack is pretty funny but seems unreasonable. @YuliKl do you know the proper way to set up this relationship? @MikeHillberg we've been doing a lot of changing properties which would naively be strings to objects instead to allow for more customization. This could be a potential issue with that strategy? |
I don't know the right way to implement this. The issue definitely feels like a bug we should try to fix. @kmahone any ideas? |
The header is read out fine by Narrator for a |
Looking at ComboBoxAutomationPeer, we override GetNameCore, call the base to see if there is already a name set (through automation name property). If an automation name is not set, then we provide the header as the name. |
@ranjeshj I will take a look if that will work here as well (I faintly recall I tried that a few days ago to no avail but perhaps I missed something). |
@ranjeshj As I thought to recall, overriding GetNameCore() alone doesn't appear to work. Here is what I did: I created a new hstring RadioButtonsAutomationPeer::GetNameCore()
{
winrt::hstring name = __super::GetNameCore();
if (name.empty())
{
if (const auto RadioButtons = Owner().try_as<winrt::RadioButtons>())
{
name = SharedHelpers::TryGetStringRepresentationFromObject(RadioButtons.Header());
}
}
return name;
} When focus enters a RadioButtons control with a header "TestRadioButtons", the header isn't read out even though GetNameCore() returns the correct value: Is the ComboBoxAutomationPeer doing anything else here? |
I don't see anything else that might affect it in ComboBox. I do notice that in the case of ComboBox, ComboBox can take focus, so that might be when Narrator is reading it out. Following up with accessibility folks. |
These are the 3 requirements for the screen reader to read it out.
Can you inspect the tree via Accessibility Insights and see we are meeting these. I suspect #3 is what might be missing. |
@ranjeshj Sorry for the late reply. I created the following test page: As you can see, I have a ComboBox with the header "ComboBoxHeader" and a RadioButtons instance with the header "RadioButtonsHeader". Narrator reads out the ComboBox header correctly, but fails to mention the RadioButtons header when stepping into the RadioButtons control with focus, Accessibility insights gives me the following for these two controls: ComboBox
What I can notice is that for the ComboBox, the header is actually part of the control. For the RadioButtons control, however, it looks like the header is just acting as a stand-alone text component. @ranjeshj Do these findings help you? |
Note in PowerToys, we got flagged for accessibility on this |
@ranjeshj Are the images above helpful and if yes, what would be the next steps here? (If not, please let me know what additional images/gifs I should upload.) |
@StephenLPeters @MikeHillberg thoughts ? |
@ranjeshj @StephenLPeters @MikeHillberg I want to point out that we still have the workaround mentioned above available to use if this should be fixed soon and providing proper support (this might be an ItemsRepeater issue where it might lack some support for a control header?) would take longer. |
@Felix-Dev while yes but when @StephenLPeters responds with the item below, it doesn't exactly inspire confidence to adopt
also if we adopt the hack, how would the hack work with the fix as if adopted, we could take the fix without realizing it. |
Maybe, to fix this "properly", from a UIA perspective, RadioButtons should be a panel or something similar so that Narrator will perceive it as a control with children. That way, it would announce the header and then the selected item while also allowing users to understand the control easier conceptually. |
@crutkas I am not entirely sure I understand your comment. The workaround using the TextBlock would be WinUI internal so customers such as PowerToys would just see that the header is pronounced as expected when focusing the RadioButtons control. Once WinUI has a proper fix ready, the workaround would be removed in a new WinUI version and customers won't notice any difference. I agree with the sentiment expressed here though that we should strive to get this fixed without using such a workaround as other headered controls like the ComboBox also get the job done without it. @chingucoding Sounds good to me though as I confessed some time ago, I am a novice to all things UIA considered so I will likely take some time tomorrow to read up more on this. |
Ah, i thought you wanted the PT code base to have the workaround |
Windows Terminal will probably get flagged for accessibility on this too. |
FWIW: In good old WinForms, a group of radio buttons was a true groupbox container which contained the radio buttons. It had its own name (the label), role (group), and would be picked up by the ancestry heuristics of screen readers when focus shifted into the group. The radio buttons were the logical children of the group in the accessibility tree. MFC C++ used a different model, there, the label for a group was a button that was a prior sibling of the first of radio buttons, and probably had some certain MSAA flags. Screen readers such as NVDA or JAWS have heuristics to automatically speak that, too. As for comboboxes, these are different beasts: Their automation name is the label, and the currently selected item is the value. But since each radio button has its own name, the grouping logic seems to be the most sensible approach here. |
What I found is that a ListView shows up in accessibility like this: list "HeaderText" Much like the ComboBox situation. So my plan to fix this is the same for RadioButtons, so that the items will be grouped like this: group "HeaderText" Everyone good with that? |
Sounds good to me! |
I thought that microsoft/microsoft-ui-xaml#3183 might just fix this for us, but it didn't. We've got our RadioButton's all up in SettingsContainers, so they all think they're `AutomationProperties.AccessibilityView="Raw"` for some reason. If you simply add the `Content` to these, then they all end up correct in Accessibility Insights ## PR Checklist * [x] Will take care of #11248 but I can't be the one to close it. * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated
I thought that microsoft/microsoft-ui-xaml#3183 might just fix this for us, but it didn't. We've got our RadioButton's all up in SettingsContainers, so they all think they're `AutomationProperties.AccessibilityView="Raw"` for some reason. If you simply add the `Content` to these, then they all end up correct in Accessibility Insights * [x] Will take care of #11248 but I can't be the one to close it. * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated (cherry picked from commit bc4f410)
Describe the bug
Steps to reproduce the bug
Steps to reproduce the behavior:
Expected behavior
When we tab into the radio button the narrator must read the heading as well as the radio button that is in focus.
Eg: something along the lines of "abcd grouping Item 1 button 1 of 3".
Actual Behavior
It just says "Item 1, 1 of 3". It does not read out the heading set by the radiobuttons header. Setting an AutomationProperty does not fix the issue either.
Screenshots
Version Info
NuGet package version:
Microsoft.UI.Xaml.2.5.0-prerelease.200708003
Windows app type:
Additional context
Link to issue in the PowerToys repository - microsoft/PowerToys#6032
The text was updated successfully, but these errors were encountered: