Skip to content
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 Accessibility test application: Screenreader does not read ListItem contents in DataBindingDemo #307

Merged
merged 1 commit into from
Aug 19, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion Sample Applications/DataBindingDemo/AuctionItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,45 @@ protected void OnPropertyChanged(string name)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

public override string ToString()
{
// All important information conveyed visually in the AuctionItem must
// be conveyed programmatically. The use of border color is purely
// decorative, and so does not need to be exposed programmatically. The
// use of the star however in the visuals is important, as is all the
// text shown in the item. These data can be exposed programmatically
// through the UI Automation (UIA) Name property of the item by returning
// the desired string in ToString() here. That string will typically be
Copy link
Contributor

@SamBent SamBent Aug 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use ToString for this. It breaks MVVM (by putting View information in the Model), and doesn't work in general. For instance if the app had another view of an AuctionItem, or if the AuctionItem class wasn't owned by the app, you couldn't do this.

Instead set the Name property in the View, matching the visual described by that view as appropriate. The mechanics to do this: 1) declare (or add to an existing) ItemContainerStyle for the ListBox, 2) set the AutomationProperties.Name attached property in that style, 3) use data-binding to make the name depend on the data item, 4) use multi-binding if the name depends on several properties, and a converter to piece them all together.

Sketch:

<ListBox.ItemContainerStyle>
  <Style TargetType="ListBoxItem">
     <Setter Property="AutomationProperties.Name">
         <Setter.Value>
             <MultiBinding Converter="{StaticResource.MyConverter}">
                <Binding Path="SpecialFeatures"/>
                <Binding Path="Description"/>
                <Binding Path="CurrentPrice"/>
 ///>

MyConverter.Convert(object[] values, ...)
{
   SpecialFeatures specialFeatures = ...convert values[0] to SpecialFeatures...;
   string description = values[1] as string;
   double currentPrice = values[2] as double;
   return   ... Guy's code ... ;
}

// announced by a screen reader when arrowing to the item. The string is
// not overwhelming when announced, but the order in which the data is
// exposed in the string should match the order in which customers will
// want to access it. So when the customer arrows quickly through the
// list to reach an item of interest, the announcement should be ordered
// to enable that rapid navigation through the items.

// Important: A shipping app would use localized text and currency
// symbols here. It also would consider whether the simple concatenation
// of the text would provide the expected experience in all regions.
// In some regions the text might need to be returned in some other order.

// Important: The text contained inside the item is exposed through the
// Control view of the UI Automation (UIA) API. This indicates to a
// screen reader that the UI is of interest to customers. However, by
// default the star UI is not exposed in this way. Given that the
// information conveyed through the use of the star is very important,
// it must be exposed programmatically to customers. That is being
// achieved here by including related information in the accessible name
// of the item. If that information was not being included here, action
// must be taken to enable the star to be reached when a screen reader
// navigates around inside the item.

return (_specialFeatures == SpecialFeatures.Highlight ?
"SpotLight, " : "") +
"Description: " + _description + ", " +
"Current price: $" + this.CurrentPrice;
}


#region Properties Getters and Setters

public string Description
Expand Down Expand Up @@ -129,4 +168,5 @@ public int CurrentPrice

#endregion
}
}
}