WPF图形控件库






4.44/5 (32投票s)
一篇介绍WPF库的文章,用于生成可扩展的运行时可自定义图形。


引言
WPFGraph
库允许生成散点图(以及后期版本中的其他图表类型),这些图表可由用户在运行时自定义。该库支持动态加载自定义点和线渲染器,并自动生成自定义对话框,为最终用户提供一个图形用户界面来配置动态加载的内容。
背景
“散点图或散点图是一种显示类型,其中包含一个或多个散点图,每个散点图都使用笛卡尔坐标显示数据集的两个变量的值。数据显示为一组点,其中一个变量的值决定其在水平轴上的位置,另一个变量的值决定其在垂直轴上的位置。
仅当存在一个由实验者控制的变量时,散点图才指定因变量或自变量。如果存在一个由实验者系统地递增和/或递减的参数,则称其为控制参数或自变量,通常绘制在水平轴上。测量变量或因变量通常绘制在垂直轴上。如果不存在因变量,则任何类型的变量都可以绘制在任意一个轴上,散点图仅说明两个变量之间的相关程度(而非因果关系)。
散点图可以在一定的置信度范围内表明变量之间的各种相关性。相关性可以是正相关(上升)、负相关(下降)或零相关(不相关)。如果点图案从左下方向右上方倾斜,则表明所研究变量之间存在正相关。如果点图案从左上方指向右下方,则表明存在负相关。可以绘制最佳拟合线来研究变量之间的相关性。变量之间相关性的方程可以通过既定的最佳拟合程序来确定。对于线性相关,最佳拟合程序称为线性回归,并保证在有限时间内生成正确解决方案。不幸的是,没有通用的最佳拟合程序能保证为任意关系生成正确解决方案。
然而,散点图最强大的方面之一是它能够显示变量之间的非线性关系。此外,如果数据由简单关系的混合模型表示,这些关系将作为叠加的模式直观地显现出来。
例如,要显示“肺活量”(第一个变量)以及该人能屏住呼吸多久(第二个变量)的值,研究人员将选择一组人进行研究,然后测量每个人的肺活量(第一个变量)以及该人能屏住呼吸多久(第二个变量)。然后,研究人员将在散点图上绘制数据,将“肺活量”分配给水平轴,将“屏住呼吸时间”分配给垂直轴。一个肺活量为 400 cc、屏住呼吸时间为 21.7 秒的人将在散点图上的笛卡尔坐标点 (400, 21.7) 处表示为一个点。研究中所有人的散点图将使研究人员能够直观地比较数据集中的两个变量,并帮助确定这两个变量之间可能存在何种关系。”
Using the Code
WPFScatterGraph UserControl
构成了核心功能和视觉连接。WPFScatterGraph
可以像任何 WPF 控件一样添加,请记住包含相关的命名空间,如下所示;
<xmlns:graph="clr-namespace:DNBSoft.WPF.WPFGraph;assembly=WPFGraph">
<graph:WPFScatterGraph />
WPFScatterGraph
由 WPFGraphSeries
(表示一条数据线,可通过 WPFScatterGraph
的 .Series
属性访问)组成,它又由 WPFGraphDataPoint
s(一个 X 和 Y 坐标,可通过 WPFGraphSeries
的 .Points
属性访问)组成。
例如,一个显示公式 y = 2 * x
线的图表可以通过以下方式构建……
WPFGraphSeries series = new WPFGraphSeries();
for (int i = 0; i < 16; i++) {
WPFGraphDataPoint f = new WPFGraphDataPoint();
f.X = i * 2;
f.Y = i;
series.Points.Add(f);
}
graphDisplay.Series.Add(series);
……其中 graphDisplay
是一个已创建的 WPFScatterGraph
。在向系列中添加大量点时,强烈建议在将系列添加到图表之前添加这些点,以提高性能。
图表选项
所有图表选项均可通过 WPFScatterGraph
的以下属性进行访问:
AxisBrush
- 设置/获取用于渲染轴(水平轴和垂直轴)的画笔AxisThickness
- 设置/获取用于轴(水平轴和垂直轴)的线的粗细AxisVerticalWidth
- 设置/获取垂直 Y 轴与控件左侧之间的距离AxisHorizontalHeight
- 设置/获取水平 X 轴与控件底部之间的距离AxisFontSize
- 设置/获取用于渲染 X 和 Y 轴标题的字体大小AxisTitleTickBrush
- 设置/获取用于渲染轴刻度(水平轴和垂直轴)的画笔AxisTitleTickThickness
- 设置/获取轴刻度(水平轴和垂直轴)的粗细MinXRange
- 设置/获取 X 轴上显示的最小值(另请参阅MinYRange
);超出此范围的值不渲染MaxXRange
- 设置/获取 X 轴上显示的最大值(另请参阅MaxYRange
);超出此范围的值不渲染IntervalXRange
- 设置/获取 X 轴的刻度间隔(另请参阅IntervalYRange
);不影响渲染XAxisTitle
- 设置/获取 X 轴上的标题(另请参阅YAxisTitle
)
格式化
整个系列和单个数据点都可以通过 WPFGraphSeries
和 WPFGraphDataPoint
的 .PointRenderer
和 .LineRenderer
方法进行自定义渲染;这些属性分别接受 IWPFGraphPointRenderer
和 IWPFGraphLineRenderer
对象,但是 WPFGraphDataPoint
也可以设置为 null
,表示渲染系统应使用系列渲染器而不是点特定的渲染器。通常,WPFGraphDataPoint
渲染器仅用于说明单个点,而**不**用于设置整个系列的样式(尽管也可以这样做)。“格式化数据系列...”对话框(如图 3 所示)目前仅支持设置整个系列的点和线渲染器,而不支持单个数据点。可以通过在图表空间(不包括轴或轴标签空间)的任意位置右键单击来访问该对话框。“格式化数据系列...”对话框应该相对直观,因此在此不详细讨论,但将在后续版本中包含一个帮助按钮。
自定义渲染器
WPFGraph
库支持为线渲染器和点渲染器使用自定义渲染器,但它不要求重新编译库以包含新的渲染器,而是通过动态加载和反射来支持自定义渲染器。要实现自定义渲染器,步骤如下:
- 创建一个新的 DLL 项目
- 创建实现
IWPFGraphPointRenderer
和/或IWPFGraphLineRenderer
的对象 - 编译为 DLL
- 将 DLL 放在应用程序的同一目录中(未来版本可能支持任何子目录)
实现接口相对简单,但为完整起见在此进行讨论。此外,由于许多点渲染器和线渲染器将具有共同的基类,因此提供了两个辅助类:WPFGraphLineRenderers.LineBase
和 WPFGraphLineRenderers.PointBase
(以下简称 LineBase
和 PointBase
)。虽然这两个类都没有实现自定义渲染器的interface
,但继承这些类可以提供自定义渲染器所需的必要方法。
-
void render(WPFRenderParameters parameters, WPFGraphDataPoint p);
渲染位于
parameters.transpose(WPFGraphEnumerations.Axis axis, p.X), parameters.transpose(WPFGraphEnumerations.Axis axis, p.Y)
的点。WPFRenderParameters.transpose
方法会自动将非缩放坐标转换为缩放坐标。 -
event WPFGraphDelegates.RendererChangedEventDelegate RendererChanged;
当任何自定义渲染器参数发生更改时触发。
RendererChangedEventArgs
包含更改的属性、旧值和新值。 -
List<WPFGraphConfigurationParameter> getConfigurationParameters();
返回一个
WPFGraphConfigurationParameter
对象列表,指示哪些属性可以修改以及它们接受的类型(目前仅支持double
和SolidColorBrush
,但在下一个版本中将添加其他类型)。使用LineBase
或PointBase
时,应调用base.getConfigurationParameters()
,并将任何自定义属性添加到列表中,然后返回。 -
void setValue(String parameter, object value);
设置名为 parameter 的属性为给定值。使用
LineBase
或PointBase
时,在测试属性名 parameter 是否为自定义渲染器的一部分之后,应调用base.setValue()
。最好设置值的界限,但如果超出界限也不应抛出异常;例如,对于线粗细,与其在设置值为-1
时抛出异常,不如将值裁剪到0
到double.MaxValue
的界限。 -
void getValue(String parameter, object value);
获取名为 parameter 的属性的值。使用
LineBase
或PointBase
时,在测试属性名 parameter 是否为自定义渲染器的一部分之后,应调用base.getValue()
。
关注点
这是 .NET 中本应是标准功能但遗憾的是并非如此的又一个例子。
颜色选择器**不是**我的代码,而是微软提供的示例颜色选择器(保留所有权利),但应注意,它不太好,在我有时间时最终会被替换!颜色选择器目前仅支持 SolidColorBrush
es,因此在代码中手动设置非实心画笔会导致选择器崩溃。
未来工作
- 其他图表类型
- 更多默认点和线渲染器
已知bug
- 某些图表选项不会自动更新图表,这可以通过调用
IWPFGraph.Refresh()
来解决。
历史
- 版本 1.0.0.0 - 首次构建,支持散点图(散点图)
其他许可说明
请随意在您的工作中引用此内容,但请注意,使用了一个修改版的 Code Project 开放许可证 (CPOL);基本上,它与标准许可证相同,只是未经事先授权,此代码**不得**用于商业或非营利性商业用途。请参阅随附的源代码和演示文件中的license.txt或license.pdf。