WPF TextBox 边框样式触发器 IsFocused 仅在具有焦点但不是键盘焦点时才有效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36605387/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:45:25  来源:igfitidea点击:

WPF TextBox Border Style Trigger IsFocused only works if has focus but not keyboard focus

wpfxamltriggerswpf-style

提问by nocarrier

I would like a nice little orange border around my Textboxwhilst the user is typing in it (Has Focus).

Textbox当用户输入时,我想要一个漂亮的橙色小边框(有焦点)。

I defined styles for the tiggers I think I need, but there is a strange behavior.

我为我认为需要的 tigger 定义了样式,但是有一种奇怪的行为。

When the cursor is in the TextBoxand the WPF app has focus, it has a blue border.

当光标位于TextBox并且 WPF 应用程序具有焦点时,它具有蓝色边框。

But while the cursor is focused and I click outside of the app (like in visual studio) it becomes orange.

但是,当光标聚焦并且我在应用程序外部(如在 Visual Studio 中)单击时,它变为橙色。

I've tried overriding many triggers but to no avail.

我试过覆盖许多触发器,但无济于事。

This is what happens when I focus on the textbox but am focused on another app:

当我专注于文本框但专注于另一个应用程序时会发生这种情况:

Focus but outside of app

专注但在应用程序之外

This is the textbox w/focus in the app:

这是应用程序中带焦点的文本框:

Focused in the app

专注于应用程序

And here is the code:

这是代码:

CTRL Xaml:

CTRL Xml:

   <TextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" 
                                         Style="{StaticResource RegistrationTextbox}" 
                                         IsReadOnly="{Binding Path=IsFirstNameReadOnly}" Text="{Binding FirstName}"  BorderThickness="0.99">
                                        <b:Interaction.Triggers>
                                            <b:EventTrigger EventName="GotFocus">
                                                <b:InvokeCommandAction Command="{Binding GotFocusFirstNameCommand}" />
                                            </b:EventTrigger>
                                        </b:Interaction.Triggers>
                                    </TextBox>

Styles:

款式:

  <Style x:Key="RegistrationTextbox" TargetType="{x:Type TextBox}">
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>

    <Style.Triggers>
        <Trigger Property="IsReadOnly" Value="true">
            <Setter Property="Background" Value="#f2f2f2"/>
            <Setter Property="BorderBrush" Value="#f2f2f2"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Trigger>
        <Trigger Property="IsKeyboardFocused" Value="true">
            <Setter Property="BorderBrush" Value="Red"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Trigger>
        <Trigger Property="IsFocused"  Value="True">
            <Setter Property="BorderBrush" Value="#FAA634"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Trigger>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="BorderBrush" Value="#F8B963"/>
            <Setter Property="BorderThickness" Value="2"/>
        </Trigger>
    </Style.Triggers>        
</Style>

回答by Evk

Take a look at default TextBox style here: https://msdn.microsoft.com/en-us/library/cc645061%28v=vs.95%29.aspx

在此处查看默认文本框样式:https: //msdn.microsoft.com/en-us/library/cc645061%28v=vs.95%29.aspx

You will notice that in ControlTemplate there is this block:

你会注意到在 ControlTemplate 中有这个块:

     <Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
     <Grid>
           <Border x:Name="ReadOnlyVisualElement" Opacity="0" Background="#5EC9C9C9"/>
           <Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
               <ScrollViewer x:Name="ContentElement" Padding="{TemplateBinding Padding}" BorderThickness="0" IsTabStop="False"/>
           </Border>
     </Grid>
     </Border>
     <Border x:Name="DisabledVisualElement" Background="#A5F7F7F7" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}" Opacity="0" IsHitTestVisible="False"/>
     <Border x:Name="FocusVisualElement" BorderBrush="#FF6DBDD1" BorderThickness="{TemplateBinding BorderThickness}" Margin="1" Opacity="0" IsHitTestVisible="False"/>

You see here that only one Border's BorderBrush is bound to BorderBrush property of TextBox. When control goes to focused state - another border (FocusVisualElement) becomes visible and because it's positined later in visual tree - it overlays regular Border. Same is true when control goes to disabled or readonly state. So your style setters basically have no effect.

您在这里看到只有一个 Border 的 BorderBrush 绑定到 TextBox 的 BorderBrush 属性。当控件进入聚焦状态时 - 另一个边框 (FocusVisualElement) 变得可见,并且因为它稍后位于可视化树中 - 它覆盖常规边框。当控制进入禁用或只读状态时也是如此。所以你的样式设置器基本上没有效果。

Now when your are switching to another app - TextBox does not consider it focused any more (note that it does not just use IsFocused property to determine that). So it hides FocusVisualElement and here you see border color applied by your trigger.

现在,当您切换到另一个应用程序时 - TextBox 不再认为它是专注的(请注意,它不只是使用 IsFocused 属性来确定)。所以它隐藏了 FocusVisualElement,在这里您可以看到触发器应用的边框颜色。

Long story short - control developers are not forced to bind to single BorderBrush property for every possible state. They could have provided something like FocusedBorderBrush property, but they did not - so you have to overwrite ControlTemplate of TextBox (you can use default template as provided by link above and overwrite some colors).

长话短说 - 控件开发人员不必为每个可能的状态绑定到单个 BorderBrush 属性。他们可以提供类似 FocusedBorderBrush 属性的东西,但他们没有 - 所以你必须覆盖 TextBox 的 ControlTemplate (你可以使用上面链接提供的默认模板并覆盖一些颜色)。