屏幕阅读器 WPF 组样式

Posted

技术标签:

【中文标题】屏幕阅读器 WPF 组样式【英文标题】:Screenreader WPF Groupstyles 【发布时间】:2013-10-20 00:05:54 【问题描述】:

我正在尝试为GroupStyle 控件模板中的控件设置AutomationProperties.Name 属性,但它似乎什么也没产生。我在模板中的Expander 上设置了它,但即使我只是输入一些没有绑定的文本,它什么也没说。我还尝试在GroupItem 上放置一个二传手,但这也没有用。我有点不知所措。我希望组项上的属性能够解决它。

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);

    


示例.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; 


【问题讨论】:

对这个有什么想法吗? 我已经使用 VS 2015 检查了这个示例,并且 AutomationProperties 设置正确 - 我已经使用 WPF Snoop 检查了它们。我认为问题不在于 AutomationProperties,而在于用于检查它们的软件。 Microsoft 提供和推荐的一些工具无法正确阅读(我不记得名称) - 我的团队几个月前不得不处理这样的问题。 AutomationProperties 类:提供一种获取或设置AutomationPeer 元素实例的关联属性值的方法。它不适用于标准 WPF 控件。对于ListBox,有ListBoxAutomationPeer 类。 这实际上取决于您使用的屏幕阅读器,人们一直说与其他专有屏幕阅读器相比,Windows 中的原生屏幕阅读器(讲述人,您很可能正在使用)非常有限,这可能是问题的根源 我还没有测试过,但尝试唱&lt;StackPanel IsItemHost="True" /&gt; 而不是`` 我遇到了Windows narrator 的问题,显然它由于某种原因没有读取ItemsPresenter 中的内容,我花了几天时间才弄清楚这出来了。 【参考方案1】:

问题实际上在于屏幕阅读器应该如何达到该值。 Groupitems 可以通过 MSAA 从光标访问,但不能通过 UIA。 UIA 是用于 WPF 中可访问性的主要 API。

UIA 和 WPF 的核心问题是,当试图读取由光标找到的控件时(其他方式是焦点和插入符号),通常会返回主窗口。

作为我自己的屏幕阅读器开发人员,处理此问题的最佳方法是同时使用 MSAA 和 UIA。如果 UIA 没有返回任何有价值的信息,请回退到使用 MSAA。

【讨论】:

【参考方案2】:

尝试将AutomationProperties.HelpTextName 一起设置。

【讨论】:

【参考方案3】:

你可以使用DisplayMemberPath="Name":

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

或者你可以使用.ToString():

public class sample

    public string Name  set; get; 

    public string Location  set; get; 

    public override string ToString()
    
        return Name;
    

【讨论】:

以上是关于屏幕阅读器 WPF 组样式的主要内容,如果未能解决你的问题,请参考以下文章

WinApi:如何为屏幕阅读器的自绘按钮添加替代文本?

WPF ListView 样式

03媒体查询

WPF - 从组标题样式中绑定到当前项目

流文档阅读器的对齐问题 - WPF

采用WPF开发第二版OFD阅读器,持续完善中,敬请期待!