1. Brush 的作用
WPF 中 Brush 用来"绘制区域",常见于:
xml
<Border Background="LightBlue" />
<TextBlock Foreground="Red" />
<Rectangle Fill="Orange" Stroke="Black" />
<Path Fill="Blue" Stroke="DarkBlue" />
常用属性包括:
| 控件 / 图形 | 常见 Brush 属性 |
|---|---|
Control |
Background、Foreground、BorderBrush |
TextBlock |
Foreground |
Border |
Background、BorderBrush |
Shape |
Fill、Stroke |
Panel |
Background |
2. Brush 继承关系
WPF 中 Brush 的主要继承结构如下:
plaintext
System.Object
└─ DispatcherObject
└─ DependencyObject
└─ Freezable
└─ Animatable
└─ Brush
├─ SolidColorBrush
├─ GradientBrush
│ ├─ LinearGradientBrush
│ └─ RadialGradientBrush
└─ TileBrush
├─ ImageBrush
├─ DrawingBrush
├─ VisualBrush
└─ BitmapCacheBrush
关键点
| 基类 | 说明 |
|---|---|
DispatcherObject |
和 UI 线程关联 |
DependencyObject |
支持依赖属性 |
Freezable |
支持冻结,提高性能 |
Animatable |
支持动画 |
Brush |
所有画刷的抽象基类 |
3. 常见 Brush 类型
3.1 SolidColorBrush
单色画刷,最常用。
XAML
xml
<Border Background="LightBlue"
BorderBrush="DarkBlue"
BorderThickness="1" />
等价写法:
xml
<Border>
<Border.Background>
<SolidColorBrush Color="LightBlue" />
</Border.Background>
</Border>
C#
csharp
var border = new Border();
border.Background = new SolidColorBrush(Colors.LightBlue);
border.BorderBrush = Brushes.DarkBlue;
适用场景
- 普通背景色
- 文本颜色
- 边框颜色
- 图形填充
- 图形描边
3.2 Brushes
Brushes 不是 Brush 子类,而是一个静态工具类,提供预定义 SolidColorBrush。
csharp
textBlock.Foreground = Brushes.Red;
border.Background = Brushes.Transparent;
rectangle.Fill = Brushes.LightGray;
常见值:
csharp
Brushes.Black
Brushes.White
Brushes.Red
Brushes.Blue
Brushes.Transparent
Brushes.LightGray
Brushes.DarkGray
3.3 LinearGradientBrush
线性渐变画刷,颜色沿一条直线过渡。
XAML
xml
<Border Width="200" Height="100">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Red" Offset="0" />
<GradientStop Color="Yellow" Offset="0.5" />
<GradientStop Color="Blue" Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
常见方向
xml
<!-- 从左到右 -->
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0" />
<!-- 从上到下 -->
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" />
<!-- 左上到右下 -->
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1" />
C#
csharp
var brush = new LinearGradientBrush();
brush.StartPoint = new Point(0, 0);
brush.EndPoint = new Point(1, 1);
brush.GradientStops.Add(new GradientStop(Colors.Red, 0));
brush.GradientStops.Add(new GradientStop(Colors.Blue, 1));
border.Background = brush;
3.4 RadialGradientBrush
径向渐变画刷,从中心向外扩散。
XAML
xml
<Ellipse Width="150" Height="150">
<Ellipse.Fill>
<RadialGradientBrush Center="0.5,0.5"
GradientOrigin="0.3,0.3"
RadiusX="0.8"
RadiusY="0.8">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="SkyBlue" Offset="0.5" />
<GradientStop Color="DarkBlue" Offset="1" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
常用属性
| 属性 | 说明 |
|---|---|
Center |
渐变圆心 |
GradientOrigin |
渐变起始点 |
RadiusX |
X 方向半径 |
RadiusY |
Y 方向半径 |
GradientStops |
渐变颜色节点集合 |
3.5 ImageBrush
使用图片作为填充。
XAML
xml
<Rectangle Width="300" Height="150">
<Rectangle.Fill>
<ImageBrush ImageSource="/Images/bg.png"
Stretch="UniformToFill" />
</Rectangle.Fill>
</Rectangle>
常用 Stretch
| 值 | 说明 |
|---|---|
None |
不缩放 |
Fill |
填满,可能变形 |
Uniform |
等比例完整显示,可能留白 |
UniformToFill |
等比例填满,可能裁剪 |
图片平铺
xml
<Rectangle Width="300" Height="200">
<Rectangle.Fill>
<ImageBrush ImageSource="/Images/tile.png"
TileMode="Tile"
Viewport="0,0,50,50"
ViewportUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
3.6 VisualBrush
使用某个 WPF Visual 元素作为画刷。
示例
xml
<StackPanel>
<TextBlock x:Name="SourceText"
Text="VisualBrush"
FontSize="32"
Foreground="Red" />
<Rectangle Width="300" Height="100">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=SourceText}" />
</Rectangle.Fill>
</Rectangle>
</StackPanel>
适用场景
- 镜像效果
- 水印
- 控件预览
- 将复杂 UI 当作背景
注意
VisualBrush 性能成本较高,不适合大量频繁使用。
3.7 DrawingBrush
使用矢量 Drawing 作为画刷,适合轻量图案。
网格 / 纹理示例
xml
<Rectangle Width="300" Height="200">
<Rectangle.Fill>
<DrawingBrush TileMode="Tile"
Viewport="0,0,20,20"
ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="LightGray">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,10,10" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
适用场景
- 网格背景
- 斜线填充
- 简单矢量纹理
- 可重复图案
3.8 BitmapCacheBrush
BitmapCacheBrush 使用缓存后的视觉内容作为画刷,较少直接使用。
适合对某些复杂视觉内容做缓存后复用,但普通场景一般优先考虑:
- 简单颜色:
SolidColorBrush - 图片:
ImageBrush - 矢量图案:
DrawingBrush - UI 元素:
VisualBrush
4. Brush 常用公共属性
所有 Brush 都有这些常用属性:
| 属性 | 说明 |
|---|---|
Opacity |
画刷透明度 |
Transform |
绝对变换 |
RelativeTransform |
相对变换 |
Brush.Opacity
xml
<Border>
<Border.Background>
<SolidColorBrush Color="Red" Opacity="0.5" />
</Border.Background>
</Border>
注意:这是只让背景半透明。
如果写在控件上:
xml
<Border Background="Red" Opacity="0.5">
<TextBlock Text="Text" />
</Border>
整个 Border 包括子元素都会半透明。
5. 资源中定义 Brush
推荐把常用画刷放到资源里。
xml
<Window.Resources>
<SolidColorBrush x:Key="PrimaryBrush" Color="#0078D4" />
<SolidColorBrush x:Key="DangerBrush" Color="#D13438" />
</Window.Resources>
<Button Background="{StaticResource PrimaryBrush}"
Foreground="White"
Content="Save" />
如果需要主题动态切换,可以使用:
xml
<Button Background="{DynamicResource PrimaryBrush}" />
StaticResource 和 DynamicResource
| 类型 | 说明 |
|---|---|
StaticResource |
加载时解析,性能较好 |
DynamicResource |
运行时查找,适合主题切换 |
6. 使用 Brush 的注意事项
6.1 不要修改 Brushes.xxx
不推荐:
csharp
Brushes.Red.Opacity = 0.5;
推荐:
csharp
var brush = new SolidColorBrush(Colors.Red)
{
Opacity = 0.5
};
原因:Brushes.Red 是共享对象,修改后可能影响其他地方。
6.2 资源 Brush 可能被多个控件共享
xml
<Window.Resources>
<SolidColorBrush x:Key="PrimaryBrush" Color="Blue" />
</Window.Resources>
<Button Background="{StaticResource PrimaryBrush}" />
<TextBlock Foreground="{StaticResource PrimaryBrush}" />
如果在代码中修改 PrimaryBrush,所有引用它的控件都会受影响。
如果只想修改单个控件,应克隆:
csharp
var brush = button.Background as SolidColorBrush;
button.Background = brush?.Clone();
6.3 Frozen Brush 不能修改
Brush 继承自 Freezable,可能被冻结。
csharp
if (brush.IsFrozen)
{
brush = brush.Clone();
}
冻结后不能修改,但性能更好。
csharp
var brush = new SolidColorBrush(Colors.Red);
brush.Freeze();
6.4 Brush 通常和 UI 线程绑定
Brush 继承自 DispatcherObject,通常只能在创建它的 UI 线程访问。
如果需要跨线程读取,可以冻结:
csharp
var brush = new SolidColorBrush(Colors.Red);
brush.Freeze();
6.5 Transparent 和 null 不一样
xml
<Grid Background="Transparent" />
表示背景透明,但可以接收鼠标事件。
xml
<Grid Background="{x:Null}" />
表示没有背景,空白区域可能无法命中鼠标事件。
如果需要点击空白区域,应使用:
xml
<Grid Background="Transparent" />
6.6 Color 和 Brush 不是同一种类型
错误:
csharp
border.Background = Colors.Red;
正确:
csharp
border.Background = Brushes.Red;
或:
csharp
border.Background = new SolidColorBrush(Colors.Red);
6.7 动画时不要共享 Brush
如果多个控件共享同一个 Brush,动画修改颜色时可能影响多个控件。
更安全:
xml
<Button Content="Hover">
<Button.Background>
<SolidColorBrush Color="LightBlue" />
</Button.Background>
</Button>
不要多个控件共享同一个正在动画的 SolidColorBrush。
6.8 ImageBrush 注意图片路径
常见路径:
xml
<ImageBrush ImageSource="/Images/bg.png" />
跨程序集:
xml
<ImageBrush ImageSource="/YourAssemblyName;component/Images/bg.png" />
图片文件常见配置:
| Build Action | 说明 |
|---|---|
Resource |
嵌入程序集 |
Content |
复制到输出目录 |
7. 如何选择 Brush
| 需求 | 推荐 |
|---|---|
| 普通纯色 | SolidColorBrush / Brushes |
| 线性渐变 | LinearGradientBrush |
| 圆形光晕 / 径向高光 | RadialGradientBrush |
| 图片背景 | ImageBrush |
| 控件作为背景 | VisualBrush |
| 网格 / 斜线 / 纹理 | DrawingBrush |
| 需要复用固定颜色 | 资源中的 SolidColorBrush |
| 需要主题切换 | DynamicResource |
| 需要动画 | 控件独立 Brush |
| 需要高性能复用 | 冻结 Brush |
8. 总结
最常用的是:
plaintext
Brush
├─ SolidColorBrush // 单色,最常用
├─ LinearGradientBrush // 线性渐变
├─ RadialGradientBrush // 径向渐变
├─ ImageBrush // 图片填充
├─ DrawingBrush // 矢量纹理
└─ VisualBrush // UI 元素填充
实际开发中优先级通常是:
- 简单颜色用
Brushes.xxx或SolidColorBrush - 可复用颜色放到资源中
- 主题切换用
DynamicResource - 图片填充用
ImageBrush - 简单纹理用
DrawingBrush - 复杂 UI 填充才考虑
VisualBrush - 要修改或动画时,避免直接修改共享 Brush