Screenreader WPF Groupstyles
Asked Answered
C

3

37

I am trying to set the AutomationProperties.Name property for controls in a GroupStyle control template and it seems to produce nothing. I have it set on the Expander in my template but it says nothing even when I just put in some text without binding. I also tried putting a setter on the GroupItem and that also didn't work. I'm at a bit of a loss. I was hoping the property on the group item would solve it.

XAML:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="WpfApplication8.MainWindow"
        x:Name="win"
        Title="MainWindow"
        Width="640"
        Height="480">

  <Grid x:Name="LayoutRoot">
    <ListBox x:Name="lstbx"
             Margin="71,45,99,78"
             ItemsSource="{Binding ElementName=win,
                                       Path=Samples}">
      <ListBox.GroupStyle>
        <GroupStyle>
          <GroupStyle.ContainerStyle>
            <Style TargetType="{x:Type GroupItem}">
              <Setter Property="AutomationProperties.Name"
                      Value="this is a test" />
              <Setter Property="KeyboardNavigation.TabNavigation"
                      Value="Cycle" />
              <Setter Property="Template">
                <Setter.Value>
                  <ControlTemplate TargetType="{x:Type GroupItem}">
                    <Expander Name="templateLstBxExpander"
                              AutomationProperties.Name="test test test"
                              IsExpanded="True">

                      <Expander.Header>
                        <StackPanel Orientation="Horizontal">
                          <Label Name="templateLstBxExpanderHeader"
                                 Content="{Binding Path=Name}"
                                 FontWeight="Bold" />
                        </StackPanel>
                      </Expander.Header>
                      <ItemsPresenter />
                    </Expander>
                  </ControlTemplate>
                </Setter.Value>
              </Setter>
            </Style>
          </GroupStyle.ContainerStyle>
        </GroupStyle>
      </ListBox.GroupStyle>
    </ListBox>
  </Grid>
</Window>

XAML.cs:

using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace WpfApplication8
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public static readonly DependencyProperty sampleProperty = DependencyProperty.Register(
        "Samples", typeof(ObservableCollection<sample>), typeof(MainWindow), new PropertyMetadata(new ObservableCollection<sample>()));

    public ObservableCollection<sample> Samples
    {
        get
        {
            return (ObservableCollection<sample>)this.GetValue(sampleProperty);
        }

        set
        {
            this.SetValue(sampleProperty, value);
        }
    }      

    public MainWindow()
    {
        this.InitializeComponent();

         CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lstbx.ItemsSource);
        PropertyGroupDescription groupDescription = new PropertyGroupDescription("Location");
        view.GroupDescriptions.Add(groupDescription);      
        sample test = new sample();
        test.Location = "one";
        test.Name = "blah blah";
        Samples.Add(test);
        sample test2 = new sample();
        test2.Location = "two";
        test2.Name = "ya ya";
        Samples.Add(test2);

    }
}
}

sample.cs:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfApplication8
{
public class sample
{


    public string Name { set; get; }
    public string Location{ set; get; }

}
Carolinecarolingian answered 11/10, 2013 at 19:50 Comment(5)
Any thoughts on this one?Carolinecarolingian
I've checked this example with VS 2015, and AutomationProperties were set correctly - I've checked them with WPF Snoop. I think that the problem is not with AutomationProperties, but with a software used to check them. Some tools provided and recommended by Microsoft don't read them properly (I don't remember the name) - my team had to deal with such a problem a few months ago.Clan
AutomationProperties class : Provides a means of getting or setting the value of the associated properties of the instance of the AutomationPeer element. It is not for standard WPF controls. For ListBox there is ListBoxAutomationPeer class.Gabe
That's actually depends on which Screenreader you are using, people keep saying that the native one in windows (Narrator, which most likely you are using) is very limited compared to other proprietary screen reader , that might be the source of the problemPackard
I have not tested bu try sing <StackPanel IsItemHost="True" /> instead of ` <ItemsPresenter />` i had issue with windows narrator apparently it does not read stuff in ItemsPresenter for some reason it took me few days to figure this out.Raposa
C
1

The problem is really about how the screenreader is supposed to reach the value. Groupitems are accessible from cursor via MSAA, but not via UIA. UIA is the primary API to use for accessibility in WPF.

The core problem with UIA and WPF, is when trying to read controls which are found by cursor (other ways are focus and caret), usually returns the main window instead.

As a developer of a screenreader myself, the best way to deal with this is to use both MSAA and UIA. If UIA returns nothing of value, fall back to using MSAA.

Coprophilia answered 1/5, 2018 at 16:30 Comment(0)
C
0

Try setting AutomationProperties.HelpText alongside with Name.

Camm answered 13/5, 2016 at 19:30 Comment(0)
A
-1

You can use DisplayMemberPath="Name":

    <ListBox x:Name="lstbx" Margin="71,45,99,78" ItemsSource="{Binding ElementName=win, Path=Samples}" DisplayMemberPath="Name" >

enter image description here

Or you can use .ToString():

public class sample
{
    public string Name { set; get; }

    public string Location { set; get; }

    public override string ToString()
    {
        return Name;
    }
}
Astarte answered 4/2, 2016 at 4:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.