Обеспечение доступности пользовательских элементов управления в WPF - PullRequest
3 голосов
/ 24 марта 2012

У меня есть форма WPF, которая состоит из сетки из двух столбцов.

В левом столбце находятся метки элементов управления, а в правом столбце - мои элементы управления.

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

Когда форма сгенерирована, у меня есть такой код, чтобы установить метку длясвязанный элемент управления, где newControl - это созданный UserControl, а ctl.Caption просто возвращает требуемый текст метки:

Label newLabel = new Label();
newLabel.Content = ctl.Caption + ":";
newLabel.Target = newControl;

Одна проблема заключается в том, что установка Target фактически не работает.Если у меня есть подчеркивание в заголовке, мнемонический ключ не устанавливает фокус на обернутый элемент управления.Одним из обходных путей для этого может быть ручная установка фокуса на обернутый элемент управления в коде UserControl, но ...

Самая большая проблема - это доступность.Программы чтения с экрана, такие как JAWS и встроенный в Windows Narrator, не читают заголовок элемента управления, когда элемент управления получает фокус.

Я посмотрел на это: http://msdn.microsoft.com/en-us/library/windows/desktop/gg712258.aspx - что обеспечивает многоподробно, но без полезных примеров.В нем много всего о пользовательских элементах управления, что, безусловно, излишне для простого пользовательского элемента управления?

Итак, как мне правильно "прикрепить" свои ярлыки кmy UserControls?

Вы можете просмотреть код всего проекта в http://quest.codeplex.com/SourceControl/changeset/view/676933506953 - конкретный код находится в проекте EditorControls, а экземпляры UserControls создаются в ElementEditor.xaml.cs.

Ответы [ 2 ]

1 голос
/ 02 апреля 2012

Ваш newControl относится к типу Control, который не позволяет вам добавлять дополнительный контент. Если вы хотите добавить к нему некоторый контент, вам нужно использовать класс, который его поддерживает, например ContentControl или Panel (для нескольких дочерних элементов), вы можете реализовать свой собственный элемент управления, реализующий интерфейс IAddChild.

Простым решением вашей проблемы может быть:

<UserControl x:Class="UIMocks.MyCustomControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel x:Name="content"/>
</UserControl>

Кодовый код

[ContentProperty("Children")]
public partial class MyCustomControl : UserControl
{
    public MyCustomControl()
    {
        InitializeComponent();
    }

    public UIElementCollection Children { get { return content.Children; } }
}

и тогда вы можете использовать

MyCustomControl newControl = InitialiseEditorControl(ctl);
...
Label newLabel = new Label();
newLabel.Content = ctl.Caption + ":";
newControl.Children.Add(newLabel);
0 голосов
/ 28 марта 2012

хммм Я пытался воспроизвести вашу проблему в небольшом тестовом проекте, но для меня это работает ... так что я думаю, вам придется рассказать больше о том, как создаются ваши пользовательские элементы управления. Вот что у меня работает:

Я создал пустой проект (как обычно, файлы приложения и окна) и настроил сетку с двумя столбцами в моем окне:

<Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Name="Window"
        SizeToContent="WidthAndHeight">

    <Grid Name="MyGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
    </Grid>

</Window>

затем создал userControl, который расширяет класс wpf TextBox:

<TextBox x:Class="Test.MyTextBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

</TextBox>

и

с использованием System.Windows; использование System.Windows.Controls;

namespace Test
{
    public partial class MyTextBox : TextBox
    {
        public static readonly DependencyProperty CaptionProperty =
             DependencyProperty.Register("Caption", typeof(string), typeof(MyTextBox), new UIPropertyMetadata(""));
        public string Caption
        {
            get { return (string)GetValue(CaptionProperty); }
            set { SetValue(CaptionProperty, value); }
        }

        public MyTextBox()
        {
            InitializeComponent();
        }
    }
}

Это в основном текстовое поле с надписью "Подпись".

и теперь в коде моего окна:

public MainWindow()
{
    InitializeComponent();

    MyTextBox tb = new MyTextBox { Caption = "_Foo", Width = 100 };
    Label lb = new Label { Content = tb.Caption + ":", Target = tb };

    MyGrid.Children.Add(lb);
    MyGrid.Children.Add(tb);

    Grid.SetColumn(lb, 0);
    Grid.SetColumn(tb, 1);
}

и с этим, я получаю фокус на TB, когда нажимаю ALT + F (я даже могу видеть _ под F "Foo" в Ярлыке, когда просто нажимаю ALT)

Так что я думаю, что ваша проблема связана с самими вашими элементами UserControls и тем, как они создаются (например, какой шаблон)

Изменить:

Если ваш элемент управления не расширяет существующий элемент управления, а содержит элемент управления WPF, проблема, вероятно, связана с методом Focus. Вам следует добавить метод Focus (), который устанавливает фокус на правой части элемента управления, когда сам элемент управления получает фокус.

код (для UserControl, содержащего текстовое поле, к которому вы хотите получить фокус, например):

<TextBox x:Class="Test.MyTextBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Button Content="foo" Grid.Column="0" />
        <TextBox Name="TextBoxPart" Grid.Column="1" />
    </Grid> 

</TextBox>

код позади

public partial class MyTextBox : TextBox
{
    public static readonly DependencyProperty CaptionProperty =
         DependencyProperty.Register("Caption", typeof(string), typeof(MyTextBox), new UIPropertyMetadata(""));
    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }

    public MyTextBox()
    {
        InitializeComponent();
    }

    protected override void OnGotFocus(RoutedEventArgs e)
    {
        TextBoxPart.Focus();
    }
}

Редактировать 2: Однажды у меня возникла проблема с переносом фокуса на субконтроль в dataGridCell, и вот что я сделал в шаблоне:

 <ControlTemplate.Triggers>
     <Trigger Property="IsFocused" Value="True">
          <Setter TargetName="TextBoxPart" Property="FocusManager.FocusedElement" Value="{Binding ElementName=TextBoxPart}" />
     </Trigger>
 </ControlTemplate.Triggers>

Вы можете попробовать добавить это в свой шаблон. Это должно перенести ваш фокус в порядке.

Что касается доступности, я не думаю, что это поможет, но я не вижу никакого способа достичь того, чего вы хотите: - /

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...