Jaa


Accessible Data: Making your data available for all

Making sure your application is accessible for tools like screen readers is important and you should be aware of and follow the guidelines outlined in Accessibility Best Practices.

 

One place you should be mindful about accessibility is when you bind a control to data. How you make your data accessible depends on how you store your data. Consider the following example, which binds a ListBox to an ObservableCollection:

 

    public class Employee

    {

        string name;

        string type;

        string number;

        public Employee(string newName, string newType, string newNumber)

        {

            name = newName;

            type = newType;

            number = newNumber;

        }

        public string EmployeeName

        {

            set { name = value; }

            get { return name; }

        }

        public string Type

        {

            set { type = value; }

            get { return type; }

        }

        public string EmployeeNumber

        {

            set { number = value; }

            get { return number; }

        }

        public override string ToString()

        {

            return EmployeeName;

        }

    }

    public class EmployeeList : ObservableCollection<Employee>

    {

        public EmployeeList()

        {

            this.Add(new Employee("Terry Adams", "FTE", "1"));

            this.Add(new Employee("Claire O'Donnell", "FTE", "12345"));

            this.Add(new Employee("Palle Peterson", "FTE", "5678"));

            this.Add(new Employee("Amy E. Alberts", "CSG", "99222"));

            this.Add(new Employee("Stefan Hesse", "Vendor", "-"));

        }

    }

 

 

<Page x:Class="ScreenReaderTest.Window1"

    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:src="clr-namespace:ScreenReaderTest"

   >

  <StackPanel>

    <ListBox TextSearch.TextPath="Name" >

      <!--ItemsSource is usually bound to a resource, but this

      is a shorcut for the example-->

      <ListBox.ItemsSource>

        <src:EmployeeList/>

      </ListBox.ItemsSource>

    </ListBox>

  </StackPanel>

</Page>

 

The ListBox displays the string returned By Employee.ToString. Accessibility tools such as Microsoft Narrator also uses the value of ToString of the selected item to read it to the user.

 

But there might be cases where the ToString method isn’t useful for screen readers. For example, the XMLDataProvider class is an easy way to bind a control to data, but if you use this, you should realize that the default information provided to UI Automation is useless. The following example uses a XmlDataProvider to display the same information as the previous example.

 

<Page x:Class="ScreenReaderTest.Window1"

    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:src="clr-namespace:ScreenReaderTest"

   >

  <Page.Resources>

    <XmlDataProvider x:Key="Employees" XPath="/Employees/*">

      <x:XData>

        <Employees xmlns="">

          <Employee Name="Terry Adams"

                    Type="FTE" EmployeeNumber="1" />

          <Employee Name="Claire O&apos;Donnell"

                    Type="FTE" EmployeeNumber="12345" />

          <Employee Name="Palle Peterson"

                    Type="FTE" EmployeeNumber="5678" />

          <Employee Name="Amy E. Alberts"

                    Type="CSG" EmployeeNumber="99222" />

          <Employee Name="Stefan Hesse"

                    Type="Vendor" EmployeeNumber="-" />

        </Employees>

      </x:XData>

    </XmlDataProvider>

    <DataTemplate x:Key="EmployeeItemTemplate">

      <TextBlock Text="{Binding XPath=@Name}" />

    </DataTemplate>

  </Page.Resources>

  <StackPanel>

    <ListBox TextSearch.TextPath="@Name"

             ItemTemplate="{StaticResource EmployeeItemTemplate}"

             ItemsSource="{Binding Source={StaticResource Employees}}" >

    </ListBox>

  </StackPanel>

</Page>

 

In this case, the DataTemplate called EmployeeItemTemplate determines what is displayed in the ListBox, but Narrator still uses the ToString method to get the value of each item in the ListBox, which is simply the string, “System.Xml.XmlElement” To give something meaningful to Narrator, you can bind the AutomationProperties.Name property to the Employee.Name property.

 

    <ListBox ItemTemplate="{StaticResource EmployeeItemTemplate}"

             ItemsSource="{Binding Source={StaticResource Employees}}" >

      <ListBox.ItemContainerStyle>

        <Style>

          <Setter Property="AutomationProperties.Name"

                  Value="{Binding XPath=@Name}"/>

        </Style>

      </ListBox.ItemContainerStyle>

    </ListBox>

 

Now Narrator will read exactly the same thing that is displayed in the ListBox. The moral of the story is, if your data source doesn’t return an informative string in its ToString method, use the AutomationProperties.Name property to give something interesting to UI Automation.

Comments

  • Anonymous
    March 20, 2007
    I have GridView include two column and the first colum is applied with dataTemplate which make up of one checkBox and TextBlock. The dataTemplate is not available When I applied the "DisplayMemberBinding" import the xml data. The first column only show the string and not show the checkBox. I post the the part of the code. Pls help thk!      <ListView Name="CategoryList"Margin="16,59,39,35.9999999999999" IsSynchronizedWithCurrentItem="True" AllowDrop="false" ItemContainerStyle="{StaticResource MyContainerStyleKey}"  ItemsSource="{Binding Source={StaticResource ConfigData}, XPath=Song}" >        <ListView.View>          <GridView ColumnHeaderContainerStyle="{DynamicResource GridViewColumnHeaderStyle}">            <GridViewColumn CellTemplate="{DynamicResource FileCategoryTemplate}" Header="{DynamicResource Archive_FileCategories}" Width="200" DisplayMemberBinding="{Binding XPath=@Category}" />            <GridViewColumn CellTemplate="{DynamicResource FileExtensionTemplate}" Header="{DynamicResource Archive_FileExtensions}" Width="600" DisplayMemberBinding="{Binding XPath=@Extension}" />          </GridView>        </ListView.View>      </ListView>

  • Anonymous
    March 21, 2007
    When you set the DisplayMemberBinding property, the GridViewColumn ignores the CellTemplate.  You should bind the data in the DataTemplate and omit the DisplayMemberBinding.    <DataTemplate x:Key="FileCategoryTemplate">      <CheckBox Content="{Binding XPath=@Category}"/>    </DataTemplate> Hope that helps.

  • Anonymous
    April 18, 2007
    I've been creating some WPF examples to hook up with my WCF applications by using Expression Blend I