65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.89/5 (9投票s)

2017 年 7 月 24 日

CPOL

2分钟阅读

viewsIcon

26582

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 对象包含绘制文本和形状的有用方法(例如 DrawRectangleDrawEllipse)。 在我们的例子中,我们使用了 DrawLineDrawText 方法。 DrawLine 方法在指定点之间绘制一条线,DrawText 方法在指定位置绘制文本。

为了绘制刻度线,我们可以简单地绘制小的垂直线,这些垂直线等间隔 50 像素。 每条这样的垂直线下方都绘制了文本。

您可以在屏幕上看到以下输出。

请注意,当您使用这些命令来绘制内容时,您实际上是在存储一组渲染数据,这些数据稍后将由图形系统用于渲染内容。 内容不是实时绘制到屏幕上的。

我们还可以添加模糊效果或任何类型的效果。 只需调用 PushEffect 方法并将您想要的效果作为输入参数传入。 为了停止将效果应用于后续绘图,请调用 Pop 方法。

© . All rights reserved.