WPF通过修改Background的Alpha从而设置透明背景颜色

WPF通过修改Background的Alpha从而设置透明背景颜色

问题来源

在 WPF 开发中,如果直接使用 Opacity 设置控件的透明度,会影响其子控件的透明度。这是因为:

  1. Opacity 属性: OpacityUIElement 类(以及 Brush 基类)中的属性,用于控制元素的不透明度。它的取值范围是从 0 到 1,其中 0 表示完全透明,1 表示完全不透明。
  2. 继承性: 在父控件上设置 Opacity 属性时,该父控件及其所有子控件都会受到影响。这是因为子控件嵌套在父控件内部,继承了父控件的视觉属性。因此,如果将父控件的透明度设置为 0.5,那么子控件也会具有相同的透明度。

我参考了这篇文章:WPF 背景色透明度设置两种方式及区别。

通过修改背景颜色的 Alpha 值从而设置透明背景颜色,可以将其封装为 Converter 或者依赖属性,以便于快捷使用。

Color 的Alpha值介绍
  1. Alpha通道:Alpha通道控制颜色的透明度。它的取值范围是0到255,其中0表示完全透明,255表示完全不透明。通过设置Alpha值,可以使颜色半透明,从而实现更丰富的视觉效果。
  2. Color类:在WPF中,可以使用System.Windows.Media.Color类来表示颜色。这个类有一个A属性,用于设置Alpha值。例如,如果想要一个半透明的红色,可以这样设置:
Color myColor = Color.FromArgb(128, 255, 0, 0); // 128表示半透明

方法1使用Converter设置透明度

/// <summary>
/// 将 SolidColorBrush 的 alpha 值进行转换以实现透明度
/// </summary>
public class BackgroundAlphaConverter : IValueConverter
{
    /// <summary>
    /// 根据指定的值(SolidColorBrush)调整其 alpha 通道
    /// </summary>
    /// <param name="value">SolidColorBrush</param>
    /// <param name="targetType"></param>
    /// <param name="parameter">透明度参数(0 到 1)。</param>
    /// <param name="culture"></param>
    /// <returns>具有调整后 alpha 值的新 SolidColorBrush。</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var alpha = GetAlphaFromTransparency(parameter);
        if (value is SolidColorBrush solidColorBrush)
        {
            var color = solidColorBrush.Color;
            color.A = alpha;
            return new SolidColorBrush(color);
        }

        return value;
    }

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

    /// <summary>
    /// 根据透明度参数(0 到 1)计算 alpha 值
    /// </summary>
    /// <param name="parameter">透明度参数(0 到 1)</param>
    /// <returns>alpha 值(0 到 255)</returns>
    public static byte GetAlphaFromTransparency(object parameter)
    {
        var param = System.Convert.ToDouble(parameter);
        if (param < 0 || param > 1)
        {
            throw new ArgumentOutOfRangeException("透明度参数必须在0到1之间");
        }

        return (byte)(int)(255 * param);
    }
}

方法2使用附加属性设置透明度

通过附加属性实现主要实现三步:

  1. 定义附加属性
  2. 设置和获取依赖属性值
  3. 响应依赖属性变化
Demo
public class BackgroundAttachP
{
    #region ExtOpacity

    public static readonly DependencyProperty ExtOpacityProperty =
    DependencyProperty.RegisterAttached(
        "ExtOpacity",
        typeof(double),
        typeof(BackgroundAttachP),
        new PropertyMetadata(1.0, OnExtOpacityChanged));
    public static void SetExtOpacity(DependencyObject obj, double value)
    {
        if (value < 0 || value > 1)
        { 
            throw new ArgumentOutOfRangeException(nameof(value), "Alpha value must be between 0 and 1.");
        }
        obj.SetValue(ExtOpacityProperty, value);
    }

    public static double GetExtOpacity(DependencyObject obj)
    {
        return (double)obj.GetValue(ExtOpacityProperty);
    }

    private  static void OnExtOpacityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        SetControlOpacity(d);
    }

    #endregion

    #region ExtBrush

    public static readonly DependencyProperty ExtBrushProperty =
    DependencyProperty.RegisterAttached(
        "ExtBrush",
        typeof(Brush),
        typeof(BackgroundAttachP),
        new PropertyMetadata(null, OnExtBrushChanged));

    public static void SetExtBrush(DependencyObject obj, Brush value)
    {
        obj.SetValue(ExtBrushProperty, value);
    }

    public static Brush GetExtBrush(DependencyObject obj)
    {
        return (Brush)obj.GetValue(ExtBrushProperty);
    }

   private static  void OnExtBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        SetControlOpacity(d);
    }
    #endregion

    private static void SetControlOpacity(DependencyObject d)
    {
        var brush = GetExtBrush(d);
        var opacity = GetExtOpacity(d);

        if (opacity >= 0 && opacity <= 1 && brush is SolidColorBrush solidColorBrush)
        {
            var color = solidColorBrush.Color;
            color.A = (byte)(int)(255 * opacity);

            if (d is Control)
            {
                d.SetValue(Control.BackgroundProperty, new SolidColorBrush(color));
            }
            else if (d is Panel)
            {
                d.SetValue(Panel.BackgroundProperty, new SolidColorBrush(color));
            }
            else if (d is Border)
            {
                d.SetValue(Border.BackgroundProperty, new SolidColorBrush(color));
            }
        }
    }
}

使用Demo

<Window
    x:Class="TabControlOpcityDemo.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:local="clr-namespace:TabControlOpcityDemo"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="800"
    Background="White"
    mc:Ignorable="d">
    <Window.Resources>
        <local:BackgroundAlphaConverter x:Key="BackgroundAlphaConverter" />
        <SolidColorBrush
            x:Key="Color1"
            Color="#ffd04b" />
        <SolidColorBrush
            x:Key="Color2"
            Color="#CC6CE7" />
    </Window.Resources>
    <StackPanel
        Margin="100"
        local:BackgroundAttachP.ExtBrush="{StaticResource Color1}"
        local:BackgroundAttachP.ExtOpacity="0.1"
        Orientation="Vertical">
        <Label Content="外部背景颜色为黄色,透明度0.01" />
        <Label Content="未设置透明度的按钮:" />
        <Button
            Width="100"
            Height="40"
            Background="{StaticResource Color2}"
            Content="透明度为1" />
        <Label Content="用Converter实现设置透明度的按钮:" />
        <Button
            Width="100"
            Height="40"
            Background="{Binding Source={StaticResource Color2},
                                 Converter={StaticResource BackgroundAlphaConverter},
                                 ConverterParameter=0.5}"
            Content="透明度为0.5" />
        <Button
            Width="100"
            Height="40"
            Background="{Binding Source={StaticResource Color2},
                                 Converter={StaticResource BackgroundAlphaConverter},
                                 ConverterParameter=0.6}"
            Content="透明度为0.6" />
        <Button
            Width="100"
            Height="40"
            Background="{Binding Source={StaticResource Color2},
                                 Converter={StaticResource BackgroundAlphaConverter},
                                 ConverterParameter=0}"
            Content="透明度为0" />
        <Label Content="用附加实现设置透明度的按钮:" />
        <Button
            Width="100"
            Height="40"
            local:BackgroundAttachP.ExtBrush="{StaticResource Color2}"
            local:BackgroundAttachP.ExtOpacity="0.4"
            Content="附加属性 0.5" />
        <Button
            Width="100"
            Height="40"
            local:BackgroundAttachP.ExtBrush="{StaticResource Color2}"
            local:BackgroundAttachP.ExtOpacity="0.3"
            Content="附加属性 0.3" />
        <Button
            Width="100"
            Height="40"
            local:BackgroundAttachP.ExtBrush="{StaticResource Color2}"
            local:BackgroundAttachP.ExtOpacity="1"
            Content="附加属性 1" />
        <Label Content="透明度0.1相互交叠的Button:" />
        <Canvas
            Width="Auto"
            Height="Auto"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch">
            <Button
                Canvas.Left="10"
                Canvas.Top="10"
                Width="200"
                Height="100"
                Margin="15"
                local:BackgroundAttachP.ExtBrush="{StaticResource Color2}"
                local:BackgroundAttachP.ExtOpacity="0.1"
                Content="透明度0.1" />
            <Button
                Canvas.Left="100"
                Canvas.Top="40"
                Width="200"
                Height="100"
                Margin="15"
                local:BackgroundAttachP.ExtBrush="{StaticResource Color2}"
                local:BackgroundAttachP.ExtOpacity="0.1"
                Content="透明度0.1" />
            <Button
                Canvas.Left="40"
                Canvas.Top="80"
                Width="200"
                Height="100"
                Margin="15"
                local:BackgroundAttachP.ExtBrush="{StaticResource Color2}"
                local:BackgroundAttachP.ExtOpacity="0.2"
                Content="透明度0.1" />
        </Canvas>
    </StackPanel>
</Window>

效果:
在这里插入图片描述

参考文章:
[1]:https://blog.csdn.net/qq_36248270/article/details/124146595

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值