在 WPF 中使用 DrawingContext 创建自定义绘制元素






3.89/5 (9投票s)
WPF DrawingContext API 简介
引言
本文介绍了如何使用 WPF DrawingContext
API 创建自定义绘制元素。 我用一个简单的水平轴示例,可以在任何图表控件中重复使用。
背景
WPF 标准库中的大多数元素和控件(例如 ComboBox
)在内部都由多个元素组成。 如果您检查 ComboBox
的可视树,您会发现它包含一个切换按钮和一个弹出窗口。通过组合现有元素来创建元素和控件是一种首选方法,但在某些情况下可能会过度。可视树中大量的元素(甚至少量重量级元素)会导致主元素变得非常重并消耗更多内存,从而导致性能问题。
有一个解决此问题的方法,它涉及让元素使用 DrawingContext
类来控制其内容的呈现。这是一种构建复合元素非常节省内存的方式。它还简化了元素的可视树并使其更轻。
DrawingContext
是一个轻量级类,可用于呈现矩形、线条、文本或任何任意几何形状。 它还可用于向呈现的内容添加视觉效果。 在本文中,我们将以带有标签和刻度的水平轴线为例,如下图所示,并了解如何使用 DrawingContext
构建它。
使用代码
public class HorizontalAxis : FrameworkElement
{
private Pen mainPen = new Pen(Brushes.Black, 1.0);
private double startPoint = 0.0;
private double endPoint = 600.0;
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
//Draw horizontal line from startPoint to endPoint
drawingContext.DrawLine(mainPen, new Point(startPoint, ActualHeight / 2),
new Point(endPoint, ActualHeight / 2));
// Draw ticks and text
for (double i = 0.0; i <= endPoint; i++)
{
if (i % 50 == 0)
{
// Draw vertical ticks on the horizontal line drawn above.
// They are spaced apart by 50 pixels.
drawingContext.DrawLine(mainPen, new Point(i, ActualHeight / 2),
new Point(i, ActualHeight / 1.25));
// Draw text below every tick
FormattedText ft = new FormattedText(
(i).ToString(CultureInfo.CurrentCulture),
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(new FontFamily("Segoe UI"),
FontStyles.Normal,
FontWeights.Normal,
FontStretches.Normal),
12,
Brushes.Black,
null,
TextFormattingMode.Display);
drawingContext.DrawText(ft, new Point(i, ActualHeight / 1.2));
}
}
}
}
您可以在您的 XAML 文件中使用 HorizontalAxis
组件,如下所示
<local:HorizontalAxis VerticalAlignment="Center" MinHeight="20"/>
如上代码所示,我创建了一个名为 HorizontalAxis
的自定义组件,它继承自 FrameworkElement
类。 FrameworkElement
类为 HorizontalAxis 添加了对布局、事件、数据绑定和动态资源、样式和动画的支持。
但是,仍然存在绘制水平线、刻度和标签的问题。 我们可以通过重写 OnRender
方法来绘制内容。 OnRender
方法是从 UIElement
继承的可重写方法,它接收一个 DrawingContext
类型的对象作为参数。 DrawingContext
对象包含绘制文本和形状的有用方法(例如 DrawRectangle
、DrawEllipse
)。 在我们的例子中,我们使用了 DrawLine
和 DrawText
方法。 DrawLine
方法在指定点之间绘制一条线,DrawText
方法在指定位置绘制文本。
为了绘制刻度线,我们可以简单地绘制小的垂直线,这些垂直线等间隔 50 像素。 每条这样的垂直线下方都绘制了文本。
您可以在屏幕上看到以下输出。
请注意,当您使用这些命令来绘制内容时,您实际上是在存储一组渲染数据,这些数据稍后将由图形系统用于渲染内容。 内容不是实时绘制到屏幕上的。
我们还可以添加模糊效果或任何类型的效果。 只需调用 PushEffect
方法并将您想要的效果作为输入参数传入。 为了停止将效果应用于后续绘图,请调用 Pop
方法。