DynamicDataDisplay.dll是一个添加动态数据到WPF应用程序交互的可视化控件。
它允许创建线图,气泡图,热图和其他复杂的二维图。
以下代码是基于0.3.0.0版本的DLL,最新的DLL某些方法已不适用。
第一部分 安装
1、安装
右击项目,管理NUGET包,在浏览中查找:DynamicDataDisplay。可以看到已经停止更新比较久了……
因为不在维护,此控件似乎只能用于临时展示些小数量的数据,数量多的情况下性能无法保证。
除此之外,也可以在网上下载单独的DLL,引入到项目中。
2、在XAML中增加名称空间
xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
3、增加Chartplotter控件
<d3:ChartPlotter Name="plotter"/>
4、后台增加数据
ObservableDataSource<Point> currentDataFrame = new ObservableDataSource<Point>();
public MainWindow()
{
InitializeComponent();
Window_Loaded_1();
}
private void Window_Loaded_1()
{
LineGraph graphAcc_x = new LineGraph();
graphAcc_x = plotter.AddLineGraph(currentDataFrame, Colors.Red, 1, "AD_data"); //注册绘图图线,配置粗细颜色以及显示名称
plotter.FitToView();
ShowLine();
}
private void ShowLine()
{
Point point = new Point(0, 0);
for (int i = 1; i <= 512; i++)
{
point.X = i;
point.Y = i + 100;
currentDataFrame.AppendAsync(base.Dispatcher, point);
}
}
5、效果
源代码下载
6、曲线
void showcurve()
{
// Prepare data in arrays
const int N = 1000;
double[] x = new double[N];
double[] y = new double[N];
for (int i = 0; i < N; i++)
{
x[i] = i * 0.1;
y[i] = Math.Sin(x[i]);
}
// Create data sources:
var xDataSource = x.AsXDataSource();
var yDataSource = y.AsYDataSource();
CompositeDataSource compositeDataSource = xDataSource.Join(yDataSource);
// adding graph to plotter
plotter.AddLineGraph(compositeDataSource, Colors.Goldenrod, 3, "Sine");
// Force evertyhing plotted to be visible
plotter.FitToView();
}
第二部分,简单使用
如上图所示:
- 青色为线为固定的数值线,一般可用来显示上下限,或者左右限值。
- 灰色线为十字光标线,跟随鼠标移动而显示,方便读取数值。
- 可定义坐标标题
- 可定义坐标高度、宽度
- 可定义固定数值线的样式
以下代码是基于0.3.0.0版本的DLL,最新的DLL某些方法已不适用。
代码如下:
<d3:ChartPlotter x:Name="plotter">
<d3:ChartPlotter.HorizontalAxis>
<!-- 常规刻度[默认显示]
Visibility:是否显示刻度轴[Visible,Hidden]
ShowMinorTicks:是否显示短刻度线
Height:刻度轴高度,0就相当于隐藏刻度轴-->
<d3:HorizontalAxis Visibility="Visible"
ShowMinorTicks="True"
Height="30" />
<!--其中,HorizontalAxis是默认坐标类型,可以更改为以下两种类型,其余参数不变
整数刻度 <d3:HorizontalIntegerAxis/>
时间轴[年月日时分秒]刻度 <d3:HorizontalDateTimeAxis/> <d3:HorizontalTimeSpanAxis/>-->
</d3:ChartPlotter.HorizontalAxis>
<d3:ChartPlotter.VerticalAxis>
<d3:VerticalAxis />
</d3:ChartPlotter.VerticalAxis>
<!--标题-->
<d3:Header x:Name="headerx"
Content="这是曲线的主标题"
FontSize="14"
HorizontalAlignment="Center" />
<d3:VerticalAxisTitle Content="Y轴标题"
FontSize="14" />
<d3:HorizontalAxisTitle Content="X轴标题"
FontSize="14" />
<!--常数线,垂直X轴或者Y轴,StrokeDashArray不写为实线-->
<d3:HorizontalLine Value="2"
Stroke="Aqua"
StrokeThickness="3"
StrokeDashArray="4" />
<d3:VerticalLine Value="2"
Stroke="Aqua"
StrokeThickness="3"
StrokeDashArray="4,5" />
<!--十字光标,以鼠标点为原点动态垂直两个坐标轴的线,便于读数-->
<d3:CursorCoordinateGraph />
<d3:LineGraph Name="lineGraph"
Stroke="OrangeRed"
StrokeThickness="1" />
</d3:ChartPlotter>
第三部分 常用设置
1、隐藏右上角的图例
plotter.LegendVisible = false;
2、隐藏坐标的网格线
以下两种写法都可以,个人使用的版本是0.3.0.0
plotter.AxisGrid.Visibility = Visibility.Hidden;
plotter.AxisGrid.Remove();
3、取消右键菜单
plotter.Children.Remove(plotter.DefaultContextMenu);
4、禁止鼠标点击坐标时可拖动的功能
plotter.Children.Remove(plotter.MouseNavigation);
5、隐藏坐标轴
其中vAxis是XAML中坐标轴的名称
vAxis.Visibility = Visibility.Hidden;
//这是只是隐藏了,之前轴宽度多少就会留白多少
//想要不留白直接 vAxis.Width = 0 或者 hAxis.Height= 0;
6、隐藏坐标轴短刻度线
其中vAxis是XAML中坐标轴的名称
有的Dll版本是用下面这个属性
vAxis.AxisControl.DrawTicks = false;
有的是用:
vAxis.ShowMinorTicks = false;
或者
vAxis.AxisControl.ShowMinorTicks = false;
7、保存屏幕截图
需要:using Microsoft.Win32;
SaveFileDialog dlg = new SaveFileDialog(); //文件选择弹出框
dlg.Filter = "PNG (*.png)|*.png|JPEG (*.jpg)|*.jpg|BMP (*.bmp)|*.bmp|GIF (*.gif)|*.gif";
dlg.FilterIndex = 1;
dlg.AddExtension = true;
if (dlg.ShowDialog().GetValueOrDefault(false))
{
string filePath = dlg.FileName;
plotter.SaveScreenshot(filePath);//filePath:取得保存的目录
}
8、坐标显示的刻度样式
info.Tick 代表刻度值
// 这将使最X轴以百分比形式显示刻度。
hAxis.LabelProvider = new ToStringLabelProvider();
//标签字符串格式
hAxis.LabelProvider.LabelStringFormat = "{0}%";
//设置自定义格式设置工具
hAxis.LabelProvider.SetCustomFormatter(info => (info.Tick * 100).ToString());
9、十字光标的相关的属性
<!--
十字光标
AutoHide: 鼠标离开绘图仪时是否自动隐藏光标行。[默认:True]
Position: 光标的位置(在AutoHide=False的时候有效)
FollowMouse: 是否跟随鼠标光标位置。[默认:True]
CustomXFormat: X标签的自定义格式字符串。
CustomYFormat: Y标签的自定义格式字符串。
XTextMapping: x label-函数的文本映射,该函数方法根据数据中鼠标的x坐标生成文本。
YTextMapping: y label-函数的文本映射,该函数方法根据数据中鼠标的x坐标生成文本。
ShowHorizontalLine: 是否显示水平线
ShowVerticalLine: 是否显示竖线
LineStroke: 光标线的颜色
LineStrokeThickness: 光标线的粗细
LineStrokeDashArray:创建虚线
-->
<d3:CursorCoordinateGraph AutoHide="False" CustomXFormat="a" LineStroke="Aqua"/>
10、在坐标上显示十字光标线对应的刻度线
如图中红线
<!--
两条轴上的线,显示当前光标位置
ShowHorizontalLine:是否显示在X轴上光标的位置
ShowVerticalLine:是否显示在Y轴上光标的位置
-->
<d3:AxisCursorGraph ShowHorizontalLine="True" />
11、显示方形区域
<d3:RectangleHighlight Bounds="0.1, 0.6, 0.15, 0.2" StrokeThickness="2" Fill="MidnightBlue"/>:
12、线段
<d3:Segment StartPoint="0.3, 0.45" EndPoint="0.5, 0.65" Stroke="Green" StrokeThickness="2" StrokeDashArray="2"/>:
13、水平条范围条
<d3:HorizontalRange Value1="0.1"
Value2="0.15"
Fill="Green" />
同理,垂直范围条
<d3:VerticalRange Value1="0.1" Value2="0.12" Fill="Fuchsia"/>
14、其它
<d3:NumericAxis Name="doubleSelector" />
第四部分 简历应用案列
1、曲线随着坐标轴的变化动态显示固定范围内的数据点
通俗的说就是曲线实时滚动,因为默认情况下,如果显示的数据随着时间动态变化,那么曲线会在坐标轴上不断的被“挤压”在一起,以显示从开始到现在的所有数据。
有时只需要动态的查看当前时间点前后固定区间的数据情况 ,这个时候就需要动态的显示固定范围内的曲线。
代码如下:
ObservableDataSource<Point> currentDataFrame = new ObservableDataSource<Point>();
private DispatcherTimer recodertimer = new DispatcherTimer();
private void Button_Click4(object sender, RoutedEventArgs e)
{
recodertimer.Tick += new EventHandler(recodertimer_Tick);
recodertimer.Interval = TimeSpan.FromSeconds(0.1);
recodertimer.Start();
plotter.AddLineGraph(currentDataFrame, Colors.Red, 1, "这是图例");
}
private void recodertimer_Tick(object sender, EventArgs e)
{
Point point = new Point(0, 0);
point.X = ++i;
point.Y = Math.Sin(i);
currentDataFrame.AppendAsync(base.Dispatcher, point);
plotter.Viewport.FitToView();
plotter.Viewport.Visible = new System.Windows.Rect(i - 5, -1, 10, 2);
}
其中主要的就是
plotter.Viewport.Visible = new System.Windows.Rect(i - 5, -1, 10, 2);
通过设置一个固定大小的矩形区域,来显示某个动态区间的数据。
第一个值是X轴的起点,第二个是Y轴,第三个是X轴的区间大小,第四个是Y轴的区间大小。
参考:https://www.cnblogs.com/nimorl/p/9156788.html
第五部分 设置数据源
此处主要写如何在后台代码中,给曲线设置数据源。其中plotter是控件的名字
方法一:Point
ObservableDataSource<Point> currentDataFrame = new ObservableDataSource<Point>();
Point point = new Point(0, 0);
for (int i = 1; i <= 512; i++)
{
point.X = i;
point.Y = i + 100;
currentDataFrame.AppendAsync(base.Dispatcher, point);
}
方法二:CompositeDataSource
const int N = 1000;
double[] x = new double[N];
double[] y = new double[N];
for (int i = 0; i < N; i++)
{
x[i] = i;
y[i] = i;
}
var xDataSource = x.AsXDataSource();
var yDataSource = y.AsYDataSource();
CompositeDataSource compositeDataSource = xDataSource.Join(yDataSource);
plotter.AddLineGraph(compositeDataSource, Colors.Goldenrod, 3, "Sine");
方法三:EnumerableDataSource
const int N = 100;
Point[] pts = new Point[N];
for (int i = 0; i < N; i++)
{
double x = i;
pts[i] = new Point(x, x);
}
var ds = new EnumerableDataSource<Point>(pts);
ds.SetXYMapping(pt => pt);
plotter.AddLineGraph(ds);
如果是自定义的类
var ds = new EnumerableDataSource<自定义类>(自定义类列表);
ds.SetXMapping(x => x.类中的字段);
ds.SetYMapping(y => y.类中的字段);
plotter.AddLineGraph(ds, Colors.Green, 2, "Volts");
后台增加数据源
List<Point> point = new List<Point>();
for (int i = 1; i <= 3; i++)
{
Point point3 = new Point();
point3.X = i;
point3.Y = i;
point.Add(point3);
}
var ds = new EnumerableDataSource<Point>(point);
ds.SetXYMapping(pt => pt);
lineGraph.DataSource=ds;
坐标轴
<!--X轴-->
<d3:ChartPlotter.MainHorizontalAxis>
<d3:HorizontalAxis x:Name="hAxis"
ShowMinorTicks="False" />
</d3:ChartPlotter.MainHorizontalAxis>
<!--Y轴-->
<d3:ChartPlotter.MainVerticalAxis>
<d3:VerticalAxis Visibility="Hidden" />
</d3:ChartPlotter.MainVerticalAxis>
固定比例位置显示控件
用比例,指示在显示区域什么位置显示其它控件
<d3:PositionalViewportUIContainer Position="0.5,0.5">
<Button Height="30"
Content="这里是固定比例位置的控件" />
</d3:PositionalViewportUIContainer>
标跟随,动态指示数据
随着鼠标移动,曲线动态显示与鼠标横坐标相同位置的点的值
借van久作者的文章插图:
<d3:VerticalLine x:Name="vLine1"
Value="{Binding ElementName=dataFollowChart, Path=MarkerPosition.X}"
StrokeThickness="2"
Stroke="Violet"
StrokeDashArray="4,5"
IsEnabled="False" />
<d3:HorizontalLine x:Name="hLine1"
Value="{Binding ElementName=dataFollowChart, Path=MarkerPosition.Y}"
StrokeThickness="2"
Stroke="Violet"
StrokeDashArray="4,5"
IsEnabled="False" />
<d3:DataFollowChart Name="dataFollowChart"
PointSource="{Binding ElementName=lineGraph}">
<DataTemplate>
<Grid d3:ViewportPanel.ScreenOffsetY="16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle RadiusX="3"
RadiusY="3"
Stroke="LightGray"
Fill="#99FFFFFF"
Grid.Row="0"
Grid.RowSpan="2" />
<Ellipse Width="10"
Height="10"
Fill="LightGreen"
Stroke="Green"
Grid.Row="0" />
<TextBlock Name="tb"
Margin="2,15,2,0"
Grid.Row="1">
<TextBlock Text="{Binding Position.X, StringFormat=G3}" />;
<TextBlock Text="{Binding Position.Y, StringFormat=G3}" />
</TextBlock>
</Grid>
</DataTemplate>
</d3:DataFollowChart>