WPF通过修改Background的Alpha从而设置透明背景颜色
问题来源
在 WPF 开发中,如果直接使用 Opacity
设置控件的透明度,会影响其子控件的透明度。这是因为:
- Opacity 属性:
Opacity
是UIElement
类(以及Brush
基类)中的属性,用于控制元素的不透明度。它的取值范围是从 0 到 1,其中 0 表示完全透明,1 表示完全不透明。 - 继承性: 在父控件上设置
Opacity
属性时,该父控件及其所有子控件都会受到影响。这是因为子控件嵌套在父控件内部,继承了父控件的视觉属性。因此,如果将父控件的透明度设置为 0.5,那么子控件也会具有相同的透明度。
我参考了这篇文章:WPF 背景色透明度设置两种方式及区别。
通过修改背景颜色的 Alpha 值从而设置透明背景颜色,可以将其封装为 Converter 或者依赖属性,以便于快捷使用。
Color 的Alpha值介绍
- Alpha通道:Alpha通道控制颜色的透明度。它的取值范围是0到255,其中0表示完全透明,255表示完全不透明。通过设置Alpha值,可以使颜色半透明,从而实现更丰富的视觉效果。
- 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使用附加属性设置透明度
通过附加属性实现主要实现三步:
- 定义附加属性
- 设置和获取依赖属性值
- 响应依赖属性变化
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