You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何仅修改TextBox的Focused视觉状态边框笔刷?解决样式应用后控件消失问题

解决TextBox焦点状态下修改边框笔刷的问题

嗨,我来帮你搞定这个问题~你遇到的TextBox凭空消失的情况,几乎可以肯定是因为自定义样式时没保留TextBox的核心控件模板结构——默认模板里包含了TextBox必须的视觉元素(比如承载内容的滚动容器),如果你的样式只写了视觉状态却漏掉这些关键部分,控件自然没东西可渲染啦。

下面给你两种靠谱的实现方式,都能只修改Focused状态的边框笔刷,同时保证TextBox正常显示:

方式一:用Trigger实现(更简洁)

这种方式代码量少,适合简单的状态修改:

<Style TargetType="{x:Type TextBox}">
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="BorderBrush" Value="#FFABADB3"/> <!-- 默认边框颜色 -->
    <Setter Property="Background" Value="#FFFFFFFF"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <!-- 核心边框元素,后面要通过TargetName修改它的笔刷 -->
                <Border x:Name="border" 
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Background="{TemplateBinding Background}"
                        SnapsToDevicePixels="True">
                    <!-- 必须保留的内容容器,WPF靠它识别TextBox的输入区域 -->
                    <ScrollViewer x:Name="PART_ContentHost" 
                                  Focusable="false" 
                                  HorizontalScrollBarVisibility="Hidden"
                                  VerticalScrollBarVisibility="Hidden"/>
                </Border>
                <ControlTemplate.Triggers>
                    <!-- 保留默认的禁用状态效果 -->
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                    </Trigger>
                    <!-- 保留默认的鼠标悬停效果(可选,不想要可以删掉) -->
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
                    </Trigger>
                    <!-- 重点:修改焦点状态下的边框笔刷 -->
                    <Trigger Property="IsFocused" Value="true">
                        <Setter Property="BorderBrush" TargetName="border" Value="#FF0078D7"/>
                        <!-- 可选:焦点时增加边框厚度,让效果更明显 -->
                        <!-- <Setter Property="BorderThickness" TargetName="border" Value="2"/> -->
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

方式二:用VisualStateManager实现(更贴近原生状态管理)

如果你习惯用VisualState来控制状态切换,这种方式更符合WPF的原生状态管理逻辑:

<Style TargetType="{x:Type TextBox}">
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="BorderBrush" Value="#FFABADB3"/>
    <Setter Property="Background" Value="#FFFFFFFF"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <Border x:Name="border" 
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Background="{TemplateBinding Background}"
                        SnapsToDevicePixels="True">
                    <ScrollViewer x:Name="PART_ContentHost" 
                                  Focusable="false" 
                                  HorizontalScrollBarVisibility="Hidden"
                                  VerticalScrollBarVisibility="Hidden"/>
                </Border>
                <VisualStateManager.VisualStateGroups>
                    <!-- 通用状态组:正常、悬停、禁用 -->
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" 
                                                              Storyboard.TargetName="border">
                                    <EasingColorKeyFrame KeyTime="0" Value="#FF7EB4EA"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Disabled">
                            <Storyboard>
                                <DoubleAnimation Duration="0" To="0.56" 
                                                 Storyboard.TargetProperty="Opacity" 
                                                 Storyboard.TargetName="border"/>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                    <!-- 焦点状态组:未聚焦、已聚焦 -->
                    <VisualStateGroup x:Name="FocusStates">
                        <VisualState x:Name="Unfocused"/>
                        <VisualState x:Name="Focused">
                            <Storyboard>
                                <!-- 这里修改焦点时的边框颜色 -->
                                <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" 
                                                              Storyboard.TargetName="border">
                                    <EasingColorKeyFrame KeyTime="0" Value="#FF0078D7"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

关键注意点

  • 一定要保留PART_ContentHost这个ScrollViewer,这是WPF识别TextBox内容区域的标记元素,删掉它TextBox就无法正常显示输入内容了。
  • 两种方式里的颜色值你可以根据自己的需求替换成任意颜色,比如十六进制色值或者系统资源色。

内容的提问来源于stack exchange,提问作者JT Smith

火山引擎 最新活动