2015-11-27 2 views
3

Я создал пользовательский шаблон UWP (т. Е. Шаблонный). Как сделать его доступным?Как создать пользовательский элемент управления UWP (т. Е. Шаблонный) с поддержкой доступности.

Прямо сейчас, когда я пытаюсь использовать его с помощью инструментарителя Windows, он ведет себя плохо. Иногда рассказчик не видит его вообще, и иногда он сверлит вниз в дерево элементов пользовательского интерфейса внутри моего контроля, когда я этого не хочу.

Первоначально я думал, что мне просто нужно установить некоторые из свойств, связанных с автоматизацией, но они не проявили никакого видимого эффекта.

ответ

5

Так что я получил что-то с этим, когда узнал об объектах AutomationPeer. В основном каждому классу управления требуется связанный с ним класс AutomationPeer, который отображает поведение вашего конкретного элемента управления в соответствии с набором стандартов, который должен использоваться инструментами доступности.

Для простоты я сделал тривиальный класс AccessButton, который происходит непосредственно из Control. (Если вы действительно делаете кнопку, вы, вероятно, захотите извлечь из Button или ButtonBase, но у этого уже есть связанный класс AutomationPeer. Я просто делаю это трудным способом для объяснительных целей.)

Вот общий. XAML код:

<Style TargetType="local:AccessibleButton"> 
    <Setter Property="UseSystemFocusVisuals" Value="True"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="local:AccessibleButton"> 
       <Grid Background="{TemplateBinding Background}"> 
        <Border BorderThickness="10"> 
         <TextBlock x:Name="Name" Text="{TemplateBinding Label}"/> 
        </Border> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Вот код позади:

public sealed class AccessibleButton : Control 
{ 
    public AccessibleButton() 
    { 
     this.DefaultStyleKey = typeof(AccessibleButton); 
    } 

    public static DependencyProperty LabelProperty = DependencyProperty.Register(
     "Label", typeof(string), typeof(AccessibleButton), 
     PropertyMetadata.Create(string.Empty)); 

    public string Label 
    { 
     set { SetValue(LabelProperty, value); } 
     get { return (string)GetValue(LabelProperty); } 
    } 

    protected override void OnPointerPressed(PointerRoutedEventArgs e) 
    { 
     Click?.Invoke(this, EventArgs.Empty); 
    } 

    public event EventHandler Click; 
} 

И некоторые использование образца в MainPage.xaml:

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <local:AccessibleButton Background="Red" Label="Click Me!" Click="AccessibleButton_Click"/> 
    <local:AccessibleButton Background="Green" Label="No, Click Me!" Click="AccessibleButton_Click"/> 
    <local:AccessibleButton Background="Blue" Label="Ignore them, Click Me!" Click="AccessibleButton_Click"/> 
</StackPanel> 

Если вы запускаете «Рассказчик» и «Мышь» над каждой кнопкой, вы обнаружите, что она игнорирует границу кнопки (вы просто получаете небольшой звук taptaptap). Если вы наведите курсор на текст, он будет иногда читать весь текст, но часто будет читать отдельные слова плюс таинственная «пустая строка» в конце текста. Я предполагаю, что элемент управления TextBlock разбивает свой вход на отдельные объекты для каждого слова ...

Это довольно плохо.

Исправление - это AutomationPeer. Вот основной класс:

public class AccessibleButtonAutomationPeer : FrameworkElementAutomationPeer 
{ 
    public AccessibleButtonAutomationPeer(FrameworkElement owner): base(owner) 
    { 
    } 
} 

(. FrameworkElementAutomationPeer находится в пространстве имен Windows.UI.Xaml.Automation.Peers)

А в классе AccessibleButton добавить переопределение для его создания:

protected override AutomationPeer OnCreateAutomationPeer() 
{ 
    return new AccessibleButtonAutomationPeer(this); 
} 

Это еще не приносит пользы. Нам нужно добавить несколько методов. Первая позволяет остановить читателя экрана от того, чтобы увидеть внутренности нашей кнопки, реализовав метод GetChildrenCore():

protected override IList<AutomationPeer> GetChildrenCore() 
{ 
    return null; 
} 

Если вы работаете только с этим вы увидите, что ничего не делает много на все теперь. Если элемент управления получает фокус, он просто скажет только «Пользовательский». Мы можем сказать, что текст на контрольной этикетке реализован методом GetNameCore():

protected override string GetNameCore() 
{ 
    return ((AccessibleButton)Owner).Label; 
} 

Это помогает. Теперь он говорит текст кнопки с надписью всякий раз, когда мы выбираем элемент управления. Но он все еще говорит «Custom» в конце.Чтобы исправить это, мы должны сообщить системе, какой контроль она является путем реализации метода GetAutomationControlTypeCore(), чтобы указать, что элемент управления находится кнопка:

protected override AutomationControlType GetAutomationControlTypeCore() 
{ 
    return AutomationControlType.Button; 
} 

Теперь он будет говорить надпись на кнопке затем «Кнопка» ,

Это действительно полезно сейчас!

Пользователь с плохим зрением, но способным перемещаться по экрану с помощью мыши или касания, по крайней мере знал бы, что говорят эти метки на этих кнопках.


AutomationPeers также позволяют поддерживать «шаблоны взаимодействия» путем реализации интерфейса поставщика шаблонов. Для примера этой кнопки подходит шаблон Invoke. Нам необходимо реализовать IInvokeProvider так добавить его в объявлении класса: (. IInvokeProvider находится в использовании с использованием пространства имен Windows.UI.Xaml.Automation.Provider)

public class AccessibleButtonAutomationPeer : 
    FrameworkElementAutomationPeer, 
    IInvokeProvider 

Затем переопределить GetPatternCore, чтобы указать, что это поддерживается:

protected override object GetPatternCore(PatternInterface patternInterface) 
{ 
    if (patternInterface == PatternInterface.Invoke) 
    { 
     return this; 
    } 

    return base.GetPatternCore(patternInterface); 
} 

и реализовать метод IInvokeProvider.Invoke:

public void Invoke() 
{ 
    ((AccessibleButton)Owner).DoClick(); 
} 

(Для поддержки этого я перехожу тело метода AccessibleButton.OnPointerPressed из в свой собственный метод DoClick(), так что я мог бы назвать его здесь.)

Для проверки этого необходимо выбрать кнопку с помощью рассказчик и нажмите Caps Lock + Пробел для вызова функции по умолчанию элемента управления. Он будет использовать метод Invoke для вызова DoClick().

Класс AutomationPeer поддерживает гораздо больше функциональности, чем этот. Если мне удастся его реализовать, я обновлю это сообщение с более подробной информацией.

+0

спасибо, что это очень полезно – PrisonMike

Смежные вопросы