在WPF中访问UserControls

时间:2012-03-23 21:48:27

标签: wpf user-controls accessibility

我有一个WPF表单,它由两列网格组成。

在左侧列中是控件标签,在右侧列中是我的控件。

控件都是UserControls。在最简单的情况下,其中一些控件只是包装现有的WPF控件,如文本框,以便它们都实现一个通用的接口。

生成表单时,我有这样的代码来设置关联控件的标签,其中newControl是创建的UserControl,而ctl.Caption只返回所需的标签文本:

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

一个问题是设置目标实际上并不起作用。如果我在标题中有下划线,则助记键不会将焦点设置为包装控件。对此的一种解决方法可能是手动将焦点设置为UserControl代码中的包装控件 - 但是......

最大的问题是可访问性。屏幕阅读器(如JAWS和Windows内置的讲述人)在控件获得焦点时不会读取控件标题。

我看过这个:http://msdn.microsoft.com/en-us/library/windows/desktop/gg712258.aspx - 它提供了很多细节,但没有有用的例子。它有很多关于自定义控件的东西,对于一个简单的用户控件肯定有点过分了?

那么,如何将我的标签“正确”附加到我的UserControls上呢?

您可以在http://quest.codeplex.com/SourceControl/changeset/view/676933506953浏览整个项目的代码 - 特定代码在EditorControls项目中,UserControls在ElementEditor.xaml.cs中实例化。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

嗯,我试图在一个小型测试项目中重现你的问题,但对我来说它有用......所以我想你必须提供有关如何构建userControls的更多细节。这对我有用:

我创建了一个Empty项目(像往常一样只是App和Window文件)并在我的窗口中设置了一个包含2列的网格:

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

然后创建了一个扩展wpf TextBox类的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">

</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();
        }
    }
}
它基本上是一个带有&#34;标题&#34;的文本框。 DP。

现在在我的窗口代码背后:

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

有了这个,当我按下ALT + F时,我确实专注于结核病(我甚至可以在按下ALT时看到&#34; Foo&#34;在标签中的_)

所以我猜你的问题与你自己的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>

您可以尝试将其添加到模板中。这应该转移你的注意力。

关于可访问性,我不认为这会有所帮助,但我认为没有任何方法可以达到你想要的目的: - /