触发器不会改变背景。

4

我正在尝试创建一个按钮模板,以防止控件在禁用时变灰,它的工作很好,但出现问题的原因是当我在按钮属性中设置颜色后,它不会改变背景色。

这是我制作的按钮:

    <Style TargetType="Button" x:Key="TestButton">
        <Setter Property="SnapsToDevicePixels" Value="true" />
        <Setter Property="OverridesDefaultStyle" Value="true" />
        <Setter Property="MinHeight" Value="29px" />
        <Setter Property="MinWidth"  Value="103px" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="Background" Value="#EEEEEE"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border TextBlock.Foreground="{TemplateBinding Foreground}" x:Name="Border">
                        <Border.Background>
                            <SolidColorBrush  Color="{TemplateBinding Background}" />
                        </Border.Background>
                        <Border.BorderBrush>
                            <SolidColorBrush  Color="Black" />
                        </Border.BorderBrush>
                        <Border.BorderThickness>
                            <Thickness Top="0.75" Bottom="0.75" Right="0.75" Left="0.75"/>
                        </Border.BorderThickness>
                        <Border.CornerRadius>
                            <CornerRadius TopLeft="3" TopRight="3" BottomLeft="3" BottomRight="3"/>
                        </Border.CornerRadius>
                        <ContentPresenter Margin="2"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        RecognizesAccessKey="True" />
                    </Border>
                    <!--Triggers-->
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="#E1F3FD" />
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter Property="Background" Value="#C4E9FF" />
                            <Setter Property="Effect">
                                <Setter.Value>
                                    <DropShadowEffect Color="Black" Direction="500" ShadowDepth="1" BlurRadius="5" Opacity="0.5" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Background}"/>
                            <Setter Property="Opacity" Value="0.5" />
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="True"  >
                            <Setter TargetName="Border" Property="Background" Value="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Background}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
当我调用它时,会给我两个不同的结果,有效的结果如下所示:
<Button Style="{DynamicResource ResourceKey=TestButton}" Content="Button" Height="66" Name="button1" Width="149" Click="button1_Click" />

但是当我给它添加一个背景时,由于某种原因它停止了更改背景:

<Button Style="{DynamicResource ResourceKey=TestButton}" Background="Orange" Content="Button" Height="66" Name="button1" Width="149" Click="button1_Click" />

Background="Orange" 添加到样式中,你就可以开始了。 - Metro Smurf
如何解决这个问题?如果我将其添加到按钮样式中,它就无法工作,而且我也不想将其添加到我的模板中,因为它应该兼容所有颜色,因为用户将定义它。我的意思是,如果用户在运行时更改了颜色,整个模板仍应正常工作。 - Steven Borges
3个回答

5
它不会改变颜色,因为您在MainWindow.xaml中“覆盖”了定义的颜色。

这被称为依赖属性值优先级。

要了解更多信息,请查看此内容:

http://msdn.microsoft.com/en-us/library/ms743230.aspx

你的情况是在样式和触发器中定义了背景,但在MainWindow中设置了值。MainWindow中设置的值被视为本地值,而在样式中设置的值为“样式-值”。
如果您查看我给您的链接,您会发现本地值先于“样式-值”。
本地值非常强大。
这就是为什么即使禁用,您的按钮仍然是橙色的原因。属性系统将尝试在触发器触发时查找背景的值,并且它总会找到本地值,因为那是具有最高优先级的值。
为了使其正常工作,您将不得不使用SetCurrentValue而不是SetValue来设置Button的背景值。(意味着您将不得不重写Buttons代码)
看一下这个:

http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.setcurrentvalue.aspx

这个方法是由一个组件使用的,它可以在不禁用应用程序声明使用该属性的情况下编程设置自己属性的值。SetCurrentValue方法会更改该属性的有效值,但现有的触发器、数据绑定和样式仍将继续工作。
编辑:
示例以了解依赖属性值的优先级和命中测试。
<Window.Resources>
    <Style TargetType="{x:Type Grid}">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="Yellow" />
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style TargetType="{x:Type TextBlock}">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="Red" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid>
    <TextBlock Height="20" Margin="40" Text="asdfasdfa" VerticalAlignment="Bottom"/>
    <Rectangle  Height="100" VerticalAlignment="Bottom" >
        <Rectangle.Fill>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Offset="0"/>
                <GradientStop Color="White" Offset="1"/>
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
</Grid>

那么只使用模板就没有办法实际更改背景了吗?这真是太糟糕了,我讨厌它被禁用后变成灰色,所以我认为制作自己的按钮可以解决这个问题... - Steven Borges
嗨,你解决了你的问题吗?是的,有一种方法,要么使用SetCurrentValue,要么稍微耍点小花招。 - dev hedgehog
你能举个例子吗?我已经阅读了你提供的内容,但是我还没能让它起作用。 - Steven Borges
我给你发了一个例子,请看一下我的修改。如果你理解了这个例子,你就会知道如何解决你的问题。关于我给你的例子,随时可以问我任何问题。 - dev hedgehog
我看到绑定在网格上的触发器会将矩形变成黄色,而文本框触发器却不起作用。虽然我不明白为什么它会使矩形外的边框变黄。现在我感觉很愚蠢,无法理解你想告诉我的内容... - Steven Borges
显示剩余3条评论

3

2

请注意:Background属性的类型是Brush,因此您应该编写:

<Border Background="{TemplateBinding Background}" ...>
    ...
</Border>

替代

<Border ...>
    <Border.Background>
        <SolidColorBrush Color="{TemplateBinding Background}" />
    </Border.Background>
    ...
</Border>

不知道我为什么那样做,已经改了! - Steven Borges

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接