首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当列表视图(WPF)的项目发生更改时,如何强制屏幕阅读器(JAWS)通知自定义文本?

当列表视图(WPF)的项目发生更改时,如何强制屏幕阅读器(JAWS)通知自定义文本?
EN

Stack Overflow用户
提问于 2013-07-09 14:48:52
回答 3查看 2.9K关注 0票数 7

我有一个WPF应用程序,需要支持屏幕阅读器(特别是JAWS)。问题是,当列表视图项发生更改(添加、删除)时,JAWS不会发布任何消息。盲人用户完全不知道发生了什么。当试图在列表视图控件中添加/删除项目时,有没有办法强制屏幕阅读器声明一些文本?我该怎么做呢?

EN

回答 3

Stack Overflow用户

发布于 2013-07-17 14:26:12

如果JAWS阅读器不支持此功能,可以通过SpeechSynthesizer自己实现。语音播放示例:

代码语言:javascript
复制
using System.Speech.Synthesis;

SpeechSynthesizer MySpeechSynthesizer = new SpeechSynthesizer();
MySpeechSynthesizer.Speak("Hello!");

我使用了一个分配了ListBoxObservableCollection的例子。ObservableCollection是一个事件CollectionChanged,在中包含在集合 [MSDN]上执行的动作的枚举

代码语言:javascript
复制
Member name   Description
------------  ------------
Add           One or more items were added to the collection.
Move          One or more items were moved within the collection.
Remove        One or more items were removed from the collection.
Replace       One or more items were replaced in the collection.
Reset         The content of the collection changed dramatically.

event将按如下方式实现:

代码语言:javascript
复制
// Set the ItemsSource
SampleListBox.ItemsSource = SomeListBoxCollection;

// Set handler on the collection
SomeListBoxCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(SomeListBoxCollection_CollectionChanged);

private void SomeListBoxCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        // Some actions, in our case - speech
    }
}

下面是我的例子:

XAML

代码语言:javascript
复制
<Window x:Class="JAWShelp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    WindowStartupLocation="CenterScreen">

    <Grid>
        <ListBox Name="MyListBox" DisplayMemberPath="Name" SelectedIndex="0" Width="100" Height="100" Loaded="MyListBox_Loaded" />

        <WrapPanel Width="200" Height="30" Margin="40,150,0,0">
            <Button Name="AddButton" Padding="5" Content="Add item" VerticalAlignment="Bottom" Click="AddButton_Click" />
            <Button Name="RemoveButton" Padding="5" Margin="30,0,0,0" Content="Remove item" VerticalAlignment="Bottom" Click="RemoveButton_Click" />
        </WrapPanel>
    </Grid>
</Window>

Code behind

代码语言:javascript
复制
// using System.Speech.Synthesis;
// using System.Collections.ObjectModel;
// using System.Collections.Specialized;

public partial class MainWindow : Window
{
    public class Person
    {
        public string Name
        {
            get;
            set;
        }
    }

    private ObservableCollection<Person> DataForListBox = new ObservableCollection<Person>();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void MyListBox_Loaded(object sender, RoutedEventArgs e)
    {
        DataForListBox.Add(new Person()
        {
            Name = "Peter Orange",                
        });

        MyListBox.ItemsSource = DataForListBox;

        DataForListBox.CollectionChanged += new NotifyCollectionChangedEventHandler(DataForListBox_CollectionChanged);
    }

    private void DataForListBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            SpeechSynthesizer MySpeechSynthesizer = new SpeechSynthesizer();

            MySpeechSynthesizer.Speak("You are add item.");
        }

        if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            SpeechSynthesizer MySpeechSynthesizer = new SpeechSynthesizer();

            MySpeechSynthesizer.Speak("You are remove item.");
        }
    }

    private void AddButton_Click(object sender, RoutedEventArgs e)
    {
        DataForListBox.Add(new Person()
        {
            Name = "Jack Rider",
        });
    }

    private void RemoveButton_Click(object sender, RoutedEventArgs e)
    {
        DataForListBox.RemoveAt(1);
    }
}

没有问题,您可以添加Add/Remove项目的复制文本。您也可以使用PromptBuilder添加播放.wav文件

代码语言:javascript
复制
PromptBuilder MyPromptBuilder = new PromptBuilder();

MyPromptBuilder.AppendAudio("SomeFile.wav");
票数 3
EN

Stack Overflow用户

发布于 2015-12-05 14:24:26

JAWS只会对获得焦点的控件做出响应。我在我的应用程序中需要类似的功能,并通过以下方式解决了它。

  1. 将两个隐藏的textbox控件添加到布局中。
  2. 添加一个类以通告消息。我发现,为了使它可靠,我需要在多个控件之间传递焦点之间短暂地暂停。否则,JAWS不会可靠地宣布消息。

public class AccessibilityMessage { private AccessibilityMessage(对象发送方,字符串消息,双延迟){ DispatcherTimer sleep = new DispatcherTimer();int counter = 3;try { if (accessibilityMessageAudibleControl != null && accessibilityMessageSilentControl != null) { sleep.Interval = TimeSpan.FromMilliseconds( delay);//更新消息。accessibilityMessageAudibleControl.SetValue(AutomationProperties.NameProperty,消息);//将焦点放在静默控件上。accessibilityMessageSilentControl.IsTabStop = true;accessibilityMessageSilentControl.Focus();//将焦点置于消息上。accessibilityMessageAudibleControl.IsTabStop = true;accessibilityMessageAudibleControl.Focus();//使用计时器模拟睡眠。我们需要短暂的暂停,以便给屏幕阅读器足够的时间//来处理消息控件上的焦点。在短暂的//暂停之后,我们将焦点返回到原始控件。如果我们不像//这样暂停,屏幕阅读器将不会可靠地对消息做出反应。sleep.Tick += (s,e) => { counter--;//检查是否可以将焦点放在原始控件上。if (counter == 0) { //将焦点返回到触发消息的原始控件。if (sender != null && sender is Control) { //将焦点返回到原始控件。((控制)发送者).Focus();} //退出计时器。sleep.Stop();//通知监听器消息已经发布。if (宣告!= null)宣告(this,null);} };//开始计时。sleep.Start();} else {抛出新的异常(“辅助功能消息控件未在应用程序管理器中定义。无法公告辅助功能消息。“);}} catch (Exception ex) { ErrorDialog.Show(ex,sender);}}公共事件消息公告;public静态消息公告(object AccessibilityMessage,string message,double AccessibilityMessage= 250) { return new AccessibilityMessage(sender,message,delay);}}

  • 公告您的消息。您可以简单地发布公告,也可以使用公告的事件发布公告,然后在发布公告后执行其他工作。

发出通知,通知用户正在加载数据网格,请稍候。

//将myGrid作为发送方传递,以便在公告之后接收焦点。ApplicationManager.AccessibilityMessage.Announce(myGrid,“正在加载采购订单表,请稍候。”).Announced += (s,arg) => { //调用WEB服务检索数据。新服务= DataService DataService();svc.ListPurchasOrdersCompleted += OnListPurchaseOrders_Completed();svc.ListPurchaseOrders();};

宣布数据已加载到数据网格中。

private void OnListPurchaseOrders_Completed(object sender,AsyncCompletedEventArgs e) { try { if (e.Error == null) { myGrid.ItemsSource = e.Result();//传入myGrid作为发送方,以便在通知后接收焦点。AccessibilityMessage.Announce(myGrid,string.Format(“已将{0}个订单加载到采购订单表中。”,myGrid.Items.Count));} else {抛出e.Error;}} catch (Exception ex) { ErrorDialog.Show(ex,this);} }

通过使用它,您可以随时发布公告,只需使用宣告()调用即可。我最初是为Silverlight实现的。它也应该适用于WPF。

票数 3
EN

Stack Overflow用户

发布于 2018-09-26 13:16:34

我喜欢的方式是在UI中有一个高度为0的TextBlock:

代码语言:javascript
复制
<TextBlock
    x:Name="screenReaderText"
    Height="0"
    AutomationProperties.LiveSetting="Assertive" />

然后,我使用此方法让它读取一些内容:

代码语言:javascript
复制
public void ReadTextToScreenReader(string text)
{
    var peer = UIElementAutomationPeer.FromElement(this.screenReaderText);
    if (peer != null)
    {
        this.screenReaderText.Text = text;
        peer.RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
    }
}

它基本上是在说:“看,这个控件改变了内容,最好把它读出来。”

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17541761

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档