【问题标题】:WPF TextBox Validation Style Disappears when Mouse is over, or it has focusWPF 文本框验证样式在鼠标悬停或具有焦点时消失
【发布时间】:2025-11-23 11:30:02
【问题描述】:

我正在创建一个自定义文本框控件以具有一些默认格式设置和验证功能,包括一个接受动作或自定义函数的自定义验证属性。

在我目前的情况下,我无法使用某些人发布的属性验证框架,因为我没有权限修改数据模型对象。我也不能使用 ValidationRules,因为并非所有需要这些验证的文本框都会被绑定。

我在静态构造函数中使用了通用文本框样式,而不是自己定义,但我添加了一些数据触发器来根据我的自定义 IsValid 依赖属性设置边框和工具提示。

一切似乎都运行良好,但问题是当我将鼠标悬停在或单击验证失败的文本框时,“无效”样式消失并变为默认文本框样式。

我尝试为 IsMouseOver、IsFocused 和 IsMouseCaptured 事件(如下所示)创建一些额外的数据触发器,但无济于事。

我错过了什么吗?

静态构造函数(显示我使用的是 TextBox 样式:

    static ValidatorTextBox()
    {
        //Commenting this line out to use the default textbox style
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ValidatorTextBox), new FrameworkPropertyMetadata(typeof(TextBox)));
    }

这是我的风格:

 <Style TargetType="{x:Type local:ValidatorTextBox}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsValid}" Value="False">
            <Setter Property="BorderBrush" Value="Red" />
            <Setter Property="BorderThickness" Value="1" />
        </DataTrigger>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsRequired}" Value="True">
            <Setter Property="Background" Value="AliceBlue" />
        </DataTrigger>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsFocused}" Value="True">
            <Setter Property="BorderBrush" Value="{Binding RelativeSource={RelativeSource Self}, Path=BorderBrush}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True">
            <Setter Property="BorderBrush" Value="{Binding RelativeSource={RelativeSource Self}, Path=BorderBrush}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseCaptured}" Value="True">
            <Setter Property="BorderBrush" Value="{Binding RelativeSource={RelativeSource Self}, Path=BorderBrush}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

【问题讨论】:

    标签: wpf validation custom-controls


    【解决方案1】:

    问题很可能是由默认的 TextBox 模板引起的。在 Aero 中(我认为在其他一些主题中也类似),边框实际上是一个镶边控件,在鼠标悬停时会更改为特定颜色。由于这发生在 ControlTemplate 内部,它会覆盖通常用于拉入控件样式上的 BorderBrush 集的 TemplateBinding。最直接的解决方法是将默认 ControlTemplate 实际复制到自定义控件的默认样式中,并在其中使用带有自定义触发器的简单边框,而不是仅在包含样式中。

    <Style TargetType="{x:Type local:ValidatorTextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ValidatorTextBox}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true" >
                        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsValid" Value="False">
                            <Setter Property="Background" TargetName="Bd" Value="Red"/>
                        </Trigger>
                        <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>
            </Setter.Value>
        </Setter>
    </Style>
    

    【讨论】:

      最近更新 更多