当颜色为十六进制时触发控件背景不触发

时间:2015-11-11 17:20:47

标签: wpf xaml triggers background hex

假设我的窗口中有3个按钮:

<Button Content="Green Button" Background="LimeGreen" Style="{StaticResource ButtonStyle}" Margin="0,0,0,10" />
<Button Content="Red Button" Background="Red" Style="{StaticResource ButtonStyle}" Margin="0,0,0,10" />
<Button Content="Hex Button" Background="#FF32CD32" Style="{StaticResource ButtonStyle}" />

在app.xaml中,我创建了一个将被所有按钮使用的样式:

<Application.Resources>

    <Style x:Key="ButtonStyle" TargetType="{x:Type ButtonBase}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ButtonBase}">
                    <Border Name="border"
                        BorderThickness="1.5"
                        Padding="{TemplateBinding Padding}"
                        BorderBrush="Black"
                        Background="{TemplateBinding Background}">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="border" Property="Opacity" Value="0.9" />
                        </Trigger>

                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsPressed" Value="True" />
                                <Condition Property="Background" Value="Red" />
                            </MultiTrigger.Conditions>

                            <Setter TargetName="border" Property="Background" Value="DarkOrange" />
                        </MultiTrigger>

                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsPressed" Value="True" />
                                <Condition Property="Background" Value="LimeGreen" />
                            </MultiTrigger.Conditions>

                            <Setter TargetName="border" Property="Background" Value="Chartreuse" />
                        </MultiTrigger>
                    </ControlTemplate.Triggers>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Application.Resources>

对于前两个按钮,一切都很完美。但是,当我尝试单击第三个按钮时,没有任何反应。 即使我添加了另一个条件为“Background value =”#FF32CD32“(它应该与LimeGreen相同)的多重组合,它也不会改变任何内容。

十六进制值是否适用于触发器?

1 个答案:

答案 0 :(得分:0)

嗯,在获得WPF的更多经验之后,我决定再给它一次。答案几乎立刻就来了......

问题是,条件中提供的值被读作颜色。单独的XAML无法解析其RGB表示。让我们看看例子:

如果背景颜色为红色(已在“颜色/画笔”枚举中定义),则正在正确读取值。但是,如果提供的值是#FFABCDEF,它也是一种颜色,但它没有被定义为标准颜色。对于XAML,它只是一个普通的字符串。因此,通过提供十六进制值而不是预定义的枚举,触发器将失败。

解决方法是创建自定义转换器。它会将颜色值转换为相应的字符串表示形式。然后,当我们检查条件中的值时,转换器将为我们提供有效的字符串。

解决方案:

首先我创建了转换器,它返回有效的十六进制颜色值:

public class ColorToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Color c = (value as SolidColorBrush).Color;

        return c.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

然后,在您的样式文件中,包含已创建转换器的命名空间:

xmlns:conv="clr-namespace:ButtonTest.Converters"

在样式文件资源中(在这种情况下,它只是App.xaml):

<conv:ColorToStringConverter x:Key="ColorToStringConverter" />

最后,触发器:

<Trigger Property="IsMouseOver" Value="True">
    <Setter TargetName="border" Property="Opacity" Value="0.9" />
</Trigger>

<!-- Custom colors handling there -->
<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsPressed}" Value="True" />
        <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Background, Converter={StaticResource ColorToStringConverter}}" Value="#FF32CD32" />
    </MultiDataTrigger.Conditions>

    <Setter TargetName="border" Property="Background" Value="Chartreuse" />
</MultiDataTrigger>

<MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="IsPressed" Value="True" />
        <Condition Property="Background" Value="Red" />
    </MultiTrigger.Conditions>

    <Setter TargetName="border" Property="Background" Value="DarkOrange" />
</MultiTrigger>

<MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="IsPressed" Value="True" />
        <Condition Property="Background" Value="LimeGreen" />
    </MultiTrigger.Conditions>

    <Setter TargetName="border" Property="Background" Value="Chartreuse" />
</MultiTrigger>

密切关注触发器优先级:应在标准颜色之前声明hex值。在我的例子中,#FF32CD32与LimeGreen相同,所以如果我把它放在最后,它将覆盖标准触发器。