Rac*_*lph 5 wpf custom-controls wpf-controls
我正在开发一个从Control派生的自定义控件,并使用ControlTemplate定义.在删除所有铃声和口哨声后,控件只显示四个TextBoxes:
<Style TargetType="{x:Type local:MyControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
<StackPanel Orientation="Horizontal">
<TextBox/>
<TextBox/>
<TextBox/>
<TextBox/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)
问题是控件能够接收键盘焦点并在自身周围绘制焦点矩形(不是其中一个TextBox,而是围绕所有TextBox).在浏览窗口中的控件时,这会添加不必要的制表位.
在自定义控件上设置Focusible为false(使用样式中的setter)可以解决问题,但是这样的解决方案远非完美,因为使用该控件的开发人员可以将Focusible设置为true,这会破坏制表符停止行为.
我可以响应控件的GotKeyboardFocus事件,并在整个控件获得焦点时将焦点放在第一个TextBox上,但是当返回标签时(使用Shift + Tab),这将无法正常工作,第一个TextBox将获得焦点,而在这种情况下应该首先关注最后一个TextBox.
如何防止整个自定义控件接受键盘焦点,但允许子TextBox正常作为制表位停止?
我将创建一个实际的 UserControl 并在那里封装焦点管理。因为通过 Style 进行 Xaml 只能让您到目前为止......
这是 UserControl 的快速示例 + 它在主窗口中的使用/测试。您会注意到聚焦的矩形不再出现。为了简单起见,我没有包含 DataBindings/ViewModel 等(因为你的问题与此无关)
<UserControl x:Class="WpfApplication1.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
IsVisibleChanged="OnIsVisibleChanged" >
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtA">txtA</TextBox>
<TextBox>txtB</TextBox>
<TextBox>txtC</TextBox>
<TextBox>txtD</TextBox>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
将焦点设置在可见性上更改为代码隐藏中的第一个文本框
namespace WpfApplication1
{
public partial class MyControl : UserControl
{
private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (IsVisible && IsEnabled)
{
Keyboard.Focus(null);
Keyboard.Focus(txtA);
}
}
public MyControl()
{
InitializeComponent();
}
}
Run Code Online (Sandbox Code Playgroud)
}
在我的小测试中,我将其放在MyControl其他两个文本之间,运行时只需选项卡:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox>txt1</TextBox>
<c:MyControl/>
<TextBox>txt2</TextBox>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)