Why does TextBox Border Colour insist on and not changing in WPF?

后端 未结 2 1880
既然无缘
既然无缘 2021-01-12 13:08

As far as I understand I should be using Style triggers to update the TextBox\'s border colour when it is focused. However no matter what I do it always turns to the system

相关标签:
2条回答
  • 2021-01-12 13:46

    Try set for BorderThickness value more than 1 (by default):

    <Window.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <Trigger Property="IsFocused" Value="True">
                    <Setter Property="BorderBrush" Value="Pink" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <Grid>
        <TextBox Width="100"
                 Height="30"
                 Text="Test" 
                 BorderThickness="4" />
    </Grid>
    

    Tested on Windows Seven.

    Edit: why is this happening?

    I looked in the default style for TextBox in Blend under Windows 7, here it is ControlTemplate:

    <ControlTemplate x:Key="TextBoxControlTemplate1" TargetType="{x:Type TextBox}">
        <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
            <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
        </Microsoft_Windows_Themes:ListBoxChrome>
    
        <ControlTemplate.Triggers>
            <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    

    Here there is two parameters:

    RenderMouseOver="{TemplateBinding IsMouseOver}"
    RenderFocused="{TemplateBinding IsKeyboardFocusWithin}"
    

    They are responsible for blue gradient Border when states Focus and MouseOver and probably there stands a condition on BorderThickness and BorderBrush. If they remove / reset the blue gradient Border will disappear and will not need to set values for BorderThickness greater than 1.

    In ILSpy I found ChangeVisualState(bool) method in TextBoxBase class, here it is:

    internal override void ChangeVisualState(bool useTransitions)
    {
        if (!base.IsEnabled)
        {
            VisualStateManager.GoToState(this, "Disabled", useTransitions);
        }
        else
        {
            if (this.IsReadOnly)
            {
                VisualStateManager.GoToState(this, "ReadOnly", useTransitions);
            }
            else
            {
                if (base.IsMouseOver)
                {
                    VisualStateManager.GoToState(this, "MouseOver", useTransitions);
                }
                else
                {
                    VisualStateManager.GoToState(this, "Normal", useTransitions);
                }
            }
        }
    
        if (base.IsKeyboardFocused)
        {
            VisualStateManager.GoToState(this, "Focused", useTransitions);
        }
        else
        {
            VisualStateManager.GoToState(this, "Unfocused", useTransitions);
        }
    
        base.ChangeVisualState(useTransitions);
    }
    

    It turns out that these visual states implemented "systematically" and in Styles not present.

    0 讨论(0)
  • 2021-01-12 13:52

    Default template of TextBox has trigger which set the border brush of textBox. In case you want to override it, you need to override ControlTemplate of TextBox.

    This is how you do that:

    <Style TargetType="TextBox">
        <Setter Property="Template">
           <Setter.Value>
              <ControlTemplate TargetType="TextBox">
                  <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
                          BorderBrush="{TemplateBinding Border.BorderBrush}"
                          Background="{TemplateBinding Panel.Background}"
                          Name="border"
                          SnapsToDevicePixels="True">
                     <ScrollViewer HorizontalScrollBarVisibility="Hidden"
                                   VerticalScrollBarVisibility="Hidden"
                                   Name="PART_ContentHost"
                                   Focusable="False" />
                  </Border>
               <ControlTemplate.Triggers>
                  <Trigger Property="UIElement.IsEnabled" Value="False">
                    <Setter Property="UIElement.Opacity" TargetName="border"
                            Value="0.56"/>
                  </Trigger>
                  <Trigger Property="UIElement.IsMouseOver" Value="True">
                    <Setter Property="Border.BorderBrush" TargetName="border" 
                            Value="#FF7EB4EA"/>
                  </Trigger>
                  <Trigger Property="UIElement.IsKeyboardFocused" Value="True">
                    <Setter Property="Border.BorderBrush" TargetName="border" 
                           Value="Black"/> <-- HERE
                  </Trigger>
               </ControlTemplate.Triggers>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
     </Style>
    

    Also you might want to override MouseOver brush to Black in above template. You can do that by supplying color value for UIElement.IsMouseOver trigger.

    0 讨论(0)
自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题