wpf - 如何防止使用控件模板创建的 WPF 自定义控件围绕自身绘制焦点?

标签 wpf wpf-controls custom-controls

我正在开发一个从 Control 派生并使用 ControlTemplate 定义的自定义控件。去掉所有花里胡哨的东西后,控件只显示四个文本框:

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

问题在于该控件能够接收键盘焦点并围绕自身(不是文本框之一,而是围绕所有文本框)绘制焦点矩形。这会在浏览窗口中的控件时添加一个不必要的制表位。

在自定义控件上将 Focusible 设置为 false(在样式中使用 setter)可以解决该问题,但这样的解决方案远非完美,因为使用该控件的开发人员可能会将 Focusible 设置为 true,这会破坏制表位停止行为。

我可以响应控件的 GotKeyboardFocus 事件,并在整个控件获得焦点时将焦点放在第一个 TextBox 上,但是在回退时(使用 Shift+Tab)这将无法正常工作,第一个 TextBox 将获得焦点,而在这种情况下最后一个 TextBox 应该首先被关注。

如何防止整个自定义控件接受键盘焦点,但允许子文本框正常充当制表位?

最佳答案

我会创建一个实际的 UserControl 并在那里封装焦点管理。因为 Xaml'ing through Style 只能让你到此为止......

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

将焦点设置为可见性更改为后面代码中的第一个文本框
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();
    }
}

}

在我的小测试中,我把 MyControl在其他两个 textboze 之间,当只运行 tab 时:
<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>

关于wpf - 如何防止使用控件模板创建的 WPF 自定义控件围绕自身绘制焦点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16421497/

相关文章:

java - 使用自定义 Java 对象回调后对象仍在内存中

c# - 具有 Entity Framework 的 Wpf 应用程序无法在其他系统上运行。显示错误 50

c# - WPF : Dynamically create a grid with specified x rows and y columns with static image in each cell

wpf - GridViewColumn.CellTemplate 中的 TextBlock 文本换行不起作用

c# - 关于 Josh Smith 的示例应用程序的 MVVM 问题

ASP.net 控件回发问题(无法读取用户输入的值!)

wpf - 具有相同颜色(不透明度)和不同字体大小的两个文本 block 显示不同

c# - 图片上传和图片 slider

c# - ComboBox 向上/向下箭头键在项目重新填充后发出

.net - 使用 WIX 通过用户输入设置属性值