共用方式為


Reusing one of your strings shown visually in your Windows 8 app as the accessible name for another element

The XAML and WinJS UI frameworks do some great things for the default accessibility of your Windows 8 app. This includes setting the accessible name of your element from the text shown on it. For example, if you had a couple of buttons which show “Save” and “Cancel” (say), then a screen reader would find the accessible names of the buttons to be “Save” and “Cancel”. Without accessible names on the elements, your app can be unusable to some of your customers.

There are situations where XAML and WinJS can’t assign an accessible name to your element by default. For example, a slider or a list might have no text associated with them which could make an appropriate accessible name. And the UI framework can’t make one up. So it’s the job of the app dev to add a name, which can be quick and easy to do through the steps I describe starting at Customizing the accessibility of my XAML and WinJS Windows 8 apps – Part 1: Introduction.

Last week I was asked by someone who had a couple of editable text fields in his XAML app, how they can assign accessible names to the fields. This is another great example of a situation where it’s very important for an element to have an accessible name, but doesn’t get one by default. So I happily pointed the person who to Customizing the accessibility of my XAML and WinJS Windows 8 apps – Part 2: The XAML app, and described how a localized text string should be added to the string resources, and use it to become the AutomationProperties.Name property for the element of interest. Job done.

Then the person asked, given that there’s a useful label for the editable field already displayed visually on the screen, couldn’t they just reuse that label as the accessible name of the editable field, through use of the “labeled by” property? My answer was, “ah, well, err, good point. Yes!” I’ve been so focused on adding new localized strings for accessible names, I’d forgotten all about the very handy approach of having the accessible name of one element become the accessible name for another element.
 
While some elements on the screen have no text shown visually nearby which would be a good candidate for an accessible name, editable text fields do often have a nearby label shown. So while my suggestion would have worked, it would mean that he would then have had two text strings to manage instead of one. There’s no point in risking the strings accidentally getting out of sync in the future if you can avoid it. So it’s certainly preferable to have a single string that’s shown of the screen and is also used for the accessible name of the editable text field.

 

In XAML, say I have a TextBlock with an x:Name of “textblockUserName”. And say it’s displaying the text “User name”. By default a TextBlock will have an accessible name that’s the same as the text shown visually on the screen, which in this case is “User name”. I decide that that’s exactly what I would like the accessible name of my nearby TextBox to be, as that’s the field in which the user types their user name. So I add the following markup to my TextBox.

        <TextBox AutomationProperties.LabeledBy="{Binding ElementName=textblockUserName}"></TextBox>

Hey presto, when I turn on a screen reader and tab to my editable text field, I hear “User name”.

 

I can do a similar thing in a WinJS app, but it took a while for me to figure out a necessary step. Say I have some label shown somewhere on the screen, using a heading.

        <h4 id="labelUserName" data-win-res="{textContent: 'labelUserName'}"></h4>

Using the Inspect SDK tool, I can see that the accessible name of this heading is the same as the text shown visually on the screen. So I update my nearby input element to have its accessible name set from the accessible name of my heading element.

        <input aria-labelledby=" labelUserName"/>

I then run the Inspect tool again and point it to my input element. I can see the following:

    AriaProperties:    "labelledby= labelUserName;"

So I had successfully set the aria-labelledby attribute. But Inspect also shows me that the accessible Name property for the element is an empty string. That’s not what I expected at all.

It turns out that the element being referenced must have an accessible role set on it, if it is to be used as the target of an aria-labelledby. Some elements have a sufficient role by default, but others do not. So if you find your attempt to use aria-labelledby didn’t work, try assigning an accessible role to the target. In my case I used a role of heading. There are lots of roles to choose from, and heading seems a good match for my situation.

        <h4 id="labelUserName" data-win-res="{textContent: 'labelUserName'}" role="heading"></h4>

 

So for both XAML apps and WinJS apps, it can often only require a tiny code change to have your editable field’s accessible name set from the accessible name of a nearby text label. That means that every time you change the label that’s shown visually on the screen, your editable field’s accessible name will also get updated. Excellent!

But don’t forget – in WinJS, the target of your aria-labelledby must have an accessible role.

And don’t ask me why “aria-labelledby” has more ‘l’s than “AutomationProperties.LabeledBy”. That’s just one of life’s great mysteries.