我有一个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中实例化。
答案 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>
您可以尝试将其添加到模板中。这应该转移你的注意力。
关于可访问性,我不认为这会有所帮助,但我认为没有任何方法可以达到你想要的目的: - /