首页 > 解决方案 > WPF:在动作上设置相对于当前颜色的背景颜色

问题描述

我有一个自定义 WPF TreeView。在那里 aTreeViewItem有一个背景颜色,具体取决于它的类型。我从 中获取该信息TreeViewItem.Name并使用了触发器,如下所示。

现在,当我选择或悬停在元素上时,TreeView我希望元素保持其颜色但更亮一点。目前如下图所示,我只是为所有元素设置了相同的颜色。

如何更改该代码以使悬停颜色相对于元素具有的颜色,无论它是哪一种?

<TreeView>
    <TreeView.Resources>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TreeViewItem">                                
                        <ControlTemplate.Triggers>

                            <Trigger Property="TreeViewItem.Name" Value="TypeA">
                                <Setter Property="Background" TargetName="Bd" Value="#8BADC5"/>
                            </Trigger>
                            <Trigger Property="TreeViewItem.Name" Value="TypeB">
                                <Setter Property="Background" TargetName="Bd" Value="#FFC3AF"/>
                            </Trigger>


                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" TargetName="Bd" Value="#A5243D"/>
                            </Trigger>
                            <Trigger Property="IsFocused" Value="True">
                                <Setter Property="Background" TargetName="Bd" Value="#A5243D"/>
                            </Trigger>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter TargetName="Bd" Property="Background" Value="#A5243D"/>
                            </Trigger>

                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TreeView.Resources>
</TreeView>

标签: c#wpfcolorstreeview

解决方案


我提出了 mami 建议的扩展版本,其中更容易制定 IsMouseOver 等触发器。它包括:

  • 一个多值转换器,用于根据基值和一些转换参数计算要使用的背景画笔
  • 用于保存转换参数的附加属性
  • 在 XAML 中,一个多重绑定

作为一个简单的例子,假设要使用的颜色应通过 Color.Multiply 与 IsMouseOver 等状态确定的因子计算。

多值转换器:

public class MultiplyColorConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var baseColor = ((SolidColorBrush)values[0]).Color;
        var factor = (float)values[1];
        return new SolidColorBrush(Color.Multiply(baseColor, factor));
    }

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

转换参数附加属性:

public class ColorTransform
{
    public static float GetFactor(DependencyObject obj)
    {
        return (float)obj.GetValue(FactorProperty);
    }

    public static void SetFactor(DependencyObject obj, float value)
    {
        obj.SetValue(FactorProperty, value);
    }

    public static readonly DependencyProperty FactorProperty =
        DependencyProperty.RegisterAttached("Factor", typeof(float), typeof(ColorTransform), 
            new FrameworkPropertyMetadata(1.0F,
                FrameworkPropertyMetadataOptions.AffectsRender));
}

XAML:

<local:MultiplyColorConverter x:Key="MultiplyColorConverter"/>
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="Template">
            <Setter.Value>
            <ControlTemplate TargetType="TreeViewItem">
                <Border x:Name="Bd">
                    <Border.Background>
                        <MultiBinding Mode="OneWay" Converter="{StaticResource MultiplyColorConverter}">
                            <Binding Path="BaseColor" Mode="OneWay"/>
                            <Binding RelativeSource="{RelativeSource Self}" Path="(local:ColorTransform.Factor)" Mode="OneWay"/>
                        </MultiBinding>
                    </Border.Background>
                    <TextBlock x:Name="Text" Text="{Binding}"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Bd" Property="local:ColorTransform.Factor" Value="0.5"/>
                    </Trigger>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter TargetName="Bd" Property="local:ColorTransform.Factor" Value="0.5"/>
                    </Trigger>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter TargetName="Bd" Property="local:ColorTransform.Factor" Value="0.3"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

推荐阅读