没有显示带有控件模板的窗口的焦点虚线

时间:2017-05-25 19:27:53

标签: c# wpf xaml

如果我有一个窗口,其UI来自控件模板,则显示键盘焦点的虚线("焦点视觉")不会显示。如果我重新实现使用直接内容而不是控件模板,那么焦点视觉效果很好。

任何人都知道在使用控件模板时如何使焦点可视化?

我最初使用的是XAML,但为了排除它,我在C#中编写了演示代码。我也对基于XAML的解决方案感到满意。

enter image description here

的Class1.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

class Class1 : Window
{
    public Class1()
    {
        Title = "Class1";
        Height = 150;
        Width = 300;

        Template = new ControlTemplate() {
            VisualTree = new FrameworkElementFactory(typeof(Template1))
        };
    }

    class Template1 : StackPanel
    {
        public Template1()
        {
            Background = Brushes.White;
            Children.Add(new TextBox());
            Children.Add(new Button() { Content = "button 1" });
            Children.Add(new Button() { Content = "button 2" });
        }
    }
}

Class2.cs

using System.Windows;
using System.Windows.Controls;
class Class2 : Window
{
    public Class2()
    {
        Title = "Class2";
        Height = 150;
        Width = 300;

        Content = new StackPanel
        {
            Children =
            {
                new TextBox(),
                new Button() { Content = "button 1" },
                new Button() { Content = "button 2" },
            }
        };
    }
}

MainWindow.cs

我刚刚从MainWindow启动了自定义窗口......

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        (new Class1()).Show();
        (new Class2()).Show();
    }
}

1 个答案:

答案 0 :(得分:2)

我认为这个问题是因为Class1窗口的可视化树中没有adorner-layer,而是Class2窗口的可视化树。

previous visual tree

当一个framework-element获得键盘焦点时,它似乎试图通过一个adorner-layer分配焦点视觉风格。 (参考: FrameworkElementKeyboardNavigation的源代码)

选项#1 最简单的解决方案是更改代码,在代码中包含ContentControl(并重新模板化):

public Class1()
{
    Title = "Class1";
    Height = 150;
    Width = 300;

    Content = new ContentControl
    {
        Template = new ControlTemplate()
        {
            VisualTree = new FrameworkElementFactory(typeof(Template1))
        }
    };
}

新的视觉树具有装饰层,因此具有焦点视觉风格:

new visual tree visual style

选项#2 或者,另一种解决方案是确保您的模板有AdornerDecorator - more details here

class Template1 : Grid
{
    public Template1()
    {
        Background = Brushes.White;
        Children.Add(
            new AdornerDecorator()
            {
                Child = new StackPanel
                {
                    Children =
                    {
                        new TextBox(),
                        new Button() { Content = "button 1" },
                        new Button() { Content = "button 2" },
                    }
                }
            }
        );
    }
}

注意:我不确定为什么在重新模板ContentControl时默认添加装饰器,而不是Window的情况。 更新05/25:我们意识到,我们在使用ContentControl自定义模板时看到的装饰器来自Window的默认模板。

选项#3 如果您在XAML中进行操作,只需将元素包装在<AdornerDecorator>中:

<ControlTemplate TargetType="{x:Type local:CustomControl1}">
    <AdornerDecorator>
        <StackPanel>
            <TextBox/>
            <Button Content="Button 1"/>
            <Button Content="Button 2"/>
        </StackPanel>
    </AdornerDecorator>
</ControlTemplate>