改变类绑定的阴影颜色WPF

问题描述 投票:0回答:1

我在寻找如何在我的WPF文档中复制Google按钮在悬停时的阴影效果,发现了这个。https:/stackoverflow.coma5303105712299798。这正好回答了我的问题,但我唯一的问题是,我通常用XAML做所有前端的事情,所以我在C#的样式设计方面还没有经验。我的问题是,我想将前景色与阴影色 "绑定",这是因为在代码中,它只将其设置为灰色,这意味着我必须为我想设置的每种颜色做一个完整的其他类。以下是我现在的代码。

MainWindow. xaml:

<Button Content="shadow">
        <Button.Style>
            <Style TargetType="Button">
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="local:UI.Elevation" Value="10"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="False">
                        <Setter Property="local:UI.Elevation" Value="0"/>

                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
</Button>

UI. cs:

public static class UI
{

    public static readonly DependencyProperty ElevationProperty = DependencyProperty.RegisterAttached("Elevation", typeof(double), typeof(UI), new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsRender, null, OnRedElevationChanged));

    public static double GetElevation(this UIElement element) => element.GetValue(ElevationProperty) as double? ?? default;

    public static void SetElevation(this UIElement element, double elevation) => element.SetValue(ElevationProperty, elevation);

    private static object OnRedElevationChanged(DependencyObject d, object value)
    {
        if (d is UIElement element && value is double elevation)
            if (elevation == 0)
                element.Effect = null;
            else
            {
                Effect e = CreateElevation(elevation, element.Effect);
                if (e != null)
                    element.Effect = e;
            }
        return value;
    }

    private static Effect CreateElevation(double elevation, Effect source)
    {
        void MixShadows(DropShadowEffect nearest, DropShadowEffect matched, double balance)
        {
            matched.BlurRadius = matched.BlurRadius * (1 - balance) + nearest.BlurRadius * balance;
            matched.ShadowDepth = matched.ShadowDepth * (1 - balance) + nearest.ShadowDepth * balance;
        }
        DropShadowEffect[] shadows = new DropShadowEffect[]
        {
        new DropShadowEffect()
        {
            BlurRadius = 5,
            ShadowDepth = 1
        },
        new DropShadowEffect()
        {
            BlurRadius = 8,
            ShadowDepth = 1.5
        },
        new DropShadowEffect()
        {
            BlurRadius = 14,
            ShadowDepth = 4.5
        },
        new DropShadowEffect()
        {
            BlurRadius = 25,
            ShadowDepth = 8
        },
        new DropShadowEffect()
        {
            BlurRadius = 35,
            ShadowDepth = 13
        }
        };
        elevation = Math.Max(0, elevation / 12 * shadows.Length - 1);
        int prevIndex = (int)Math.Floor(elevation), index = (int)elevation, nextIndex = (int)Math.Ceiling(elevation);
        double approx = elevation - index;
        DropShadowEffect shadow = shadows[index];
        if (approx != 0)
            MixShadows(approx < 0 ? shadows[prevIndex] : shadows[nextIndex], shadow, Math.Abs(approx));
        bool modify = false;
        if (source is DropShadowEffect sourceShadow)
        {
            sourceShadow.BlurRadius = shadow.BlurRadius;
            sourceShadow.ShadowDepth = shadow.ShadowDepth;
            shadow = sourceShadow;
            modify = true;
        }
        shadow.Direction = 270;
        shadow.Color = Colors.Red;
        shadow.Opacity = .42;
        shadow.RenderingBias = RenderingBias.Performance;
        return modify ? null : shadow;
    }
}

为了在XAML中得到我想要的东西,我会做这样的事情。

<Button Content="shadow">
        <Button.Style>
            <Style TargetType="Button">
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="local:UI.Elevation" Value="10"/>
                        <Setter Property="local:UI.Elevation.Foreground" Value="Blue"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="False">
                        <Setter Property="local:UI.Elevation" Value="0"/>
                        <Setter Property="local:UI.Elevation.Foreground" Value="Blue"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
</Button>

但我不知道如何把这个类连接起来。local:UI.Elevation.Foreground 为了改变阴影颜色,我必须把这行从 UI.cs: shadow.Color = Colors.Red; 并将其绑定到Elevation.Foreground,但我遇到了困难。谁能帮帮我?

c# wpf binding styling shadow
1个回答
1
投票

你需要做的就是更新UI类,并添加一个新的附加属性,比如说 Color 类型 Color 并给它一个你喜欢的默认颜色。

然后,在其 OnColorChanged 处理程序,调用 OnElevationChanged 这样影子就会被重新创建。

#region Color (Attached Property)
public static readonly DependencyProperty ColorProperty =
    DependencyProperty.RegisterAttached(
        "Color",
        typeof(Color),
        typeof(UI),
        new PropertyMetadata(Colors.Black, OnColorChanged));

public static Color GetColor(DependencyObject obj)
{
    return (Color)obj.GetValue(ColorProperty);
}

public static void SetColor(DependencyObject obj, Color value)
{
    obj.SetValue(ColorProperty, value);
}

private static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    OnElevationChanged(d, GetElevation((UIElement)d));
}
#endregion

CreateElevation 方法中,为颜色添加一个新的参数,这样你就可以设置它了。

private static Effect CreateElevation(double elevation, Effect source, Color color)
{
    ...
    shadow.Color = color;
    ...
}

最后,在 OnElevationChanged 更新它,使其调用 GetColor 所以它可以通过在新的 Color 属性。

private static object OnElevationChanged(DependencyObject d, object value)
{
    if (d is UIElement element && value is double elevation)
        if (elevation == 0)
            element.Effect = null;
        else
        {
            Effect e = CreateElevation(elevation, element.Effect, GetColor(element));
            if (e != null)
                element.Effect = e;
        }
    return value;
}

示例XAML

<Button
    Width="100"
    Height="20"
    Content="shadow">
    <Button.Style>
        <Style TargetType="Button">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="local:UI.Elevation" Value="10" />
                    <Setter Property="local:UI.Color" Value="Blue" />
                </Trigger>
                <Trigger Property="IsMouseOver" Value="False">
                    <Setter Property="local:UI.Elevation" Value="5" />
                    <Setter Property="local:UI.Color" Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

: 你可以做一些重构来使所有这些都更干净,但希望这能让你开始。

© www.soinside.com 2019 - 2024. All rights reserved.