WPF样式触发器中的setter与局部值的行为不一致

本文关键字:不一致 局部 setter 样式 触发器 WPF | 更新日期: 2023-09-27 18:03:42

我正在为我的WPF应用程序使用一个自定义TextBox控件,它在泛型中有一个默认样式设置。xaml文件。我在文件中设置的模板包括以下Setter和Triggers:

<Setter Property="Background" Value="Blue" />

<Trigger Property="IsFocused" Value="True">
    <Setter Property="Background" Value="Yellow"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="BorderBrush" Value="Black"/>
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
    <Condition Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="True" />
    <Condition Binding="{Binding Path=IsFocused, RelativeSource={RelativeSource Self}}" Value="False" />
    <Condition Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Self}}" Value="False" />
    <Condition Binding="{Binding Path=Text, RelativeSource={RelativeSource Self}, Converter={StaticResource IsEmptyStringConverter}}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
    <Setter Property="Background" Value="Green" TargetName="Border" />
    <Setter Property="Foreground" Value="White"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>

如果我没有为Background属性设置一个Local值,这段代码将按预期工作。当聚焦时,我的背景变成黄色,当没有聚焦并且没有验证错误时,它变成绿色。

但是,如果我为Background属性设置了一个Local值,就像下面的代码片段一样,当其中一个触发器被触发时,Background的行为是非常奇怪的。

<custom:TextBox Background="Orange" />

    当isfocused触发器被触发时,背景保持橙色。我认为这是由于WPF的依赖属性设置优先级,它倾向于局部值而不是样式触发器中设置的值。是的,触发器肯定是触发的,因为边界刷和前景的变化。
  • 当第二个触发器(MultiDataTrigger for Validation)被触发时,背景变为绿色。
  • 本地值被忽略。

在我看来,这是不一致的。为什么第一个触发器使用我的本地值,而第二个坚持它的背景设置?这两个触发器之间有什么不同的优先级吗?

WPF样式触发器中的setter与局部值的行为不一致

样式触发器模板触发器不能更改本地值设置的值但是他们可以使用TemplatedParent模板

来改变该控件的子元素的继承属性

的例子:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Red"></Setter>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Green"></Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Button Width="100" Height="100" Background="Pink"></Button>
    </Grid>
</Window>

在示例中,按钮背景属性将保持粉红色(本地值),您可以使用Snoop

看到

但是如果你把鼠标悬停在按钮上,你会看到背景正在改变,这是因为按钮的子元素(一个Border)被它的父元素TemplatedParent和TemplatedParent. trigger改变了。再次使用Snoop查看值源