前言:上一篇介绍了LiveCharts2中图表的基本类型及示例复现,基本都是数据的展示,仅仅是数据,图表其他的一些附属属性并没有,而且横坐标都是按依次增加的,纵坐标是我们设置的数据,这一篇就讲下图表的一些其他附属属性。
笔者这里以折线图作为示例。
常用属性
折线图主要组件就是这四个,数据、坐标、提示工具、图例。
But notice in the previous code snippet we did not specify the Axes, Tooltip, Legend or the series colors, this is because LiveCharts will decide them based on the current theme of the library, you can also customize any of these properties when you require it, this article will cover the most common scenarios.
之前我们并没有设置坐标系、提示框、图例等,因为框架帮我们设置了。
一、Series
There are multiple series available in the library, you can add one or mix them all in the same chart, every series has unique properties, any image bellow is a link to an article explaining more about them.
动态库中有多个可用数据,可以在图表中添加一个或多个,每个数据都有独特的属性。
以Line Series为例介绍下它的属性
1.1 Name 、Values property
name属性没什么好说的,values属性倒是内容比较多。
The
Values
property is of typeIEnumerable<T>
, this means that you can use any object that implements theIEnumerable<T>
interface, such asArray
,List<T>
orObservableCollection<T>
, this property contains the data to plot, you can use any type as the generic argument (<T>
) as soon as you let the library how to handle it, the library already knows how to handle multiple types, but you can register any type and teach the library how to handle any object in a chart, for more information please see the mappers article.
Values属性是IEnumerable<T>类型,用户可以灵活使用这个属性,这个属性就是给图表数据去绘制的,至于IEnumerable<T>类型中的T(泛型)可以是任意类型,但是需要注册,具体的参考mappers相关文章。
SeriesCollection = new ISeries[]
{
new LineSeriesProps<int>
{
Values = new []{ 2, 5, 4, 2, 6 },
Name = "Income",
Stroke = null
},
new LineSeriesProps<int>
{
Values = new []{ 3, 7, 2, 9, 4 },
Name = "Outcome",
Stroke = null
}
};
// == 自定义类型和mapper ==
public class City
{
public string Name { get; set; }
public double Population { get; set; }
}
//我们必须让series知道怎么去处理我们自定义的city类
// 使用Mapping属性从我们自定义的city类中的一个point
// 同样也可以将map注册成全局的
// 更多mappers信息查看:
// https://lvcharts.com/docs/wpf/2.0.0-beta.300/Overview.Mappers
var citiesSeries = new LineSeriesProps<City>
{
Values = new City[]
{
new City { Name = "Tokio", Population = 9 },
new City { Name = "New York", Population = 11 },
new City { Name = "Mexico City", Population = 10 },
},
Mapping = (city, point) =>
{
// 我们数据集合中的city会被调用
// 用户必须将坐标映射到点上
// 将自定义类中的Population属性作为第一个参数(通常是Y)
point.PrimaryValue = (float)city.Population;
// 使用自定义类city的索引作为第二个参数
// (通常是 X)
point.SecondaryValue = point.Context.Index;
}
};
1.2 Data labels
Data labels are labels for every point in a series, there are multiple properties to customize them
数据标签,下面看图就明白了
new LineSeriesProps<double>
{
DataLabelsSize = 20,
DataLabelsPaint = new SolidColorPaint(SKColors.Blue),
// all the available positions at:
// https://lvcharts.com/api/2.0.0-beta.300/LiveChartsCore.Measure.DataLabelsPosition
DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.Top,
// The DataLabelsFormatter is a function
// that takes the current point as parameter
// and returns a string.
// in this case we returned the PrimaryValue property as currency
DataLabelsFormatter = (point) => point.PrimaryValue.ToString("C2"),
Values = new ObservableCollection<double> { 2, 1, 3, 5, 3, 4, 6 },
Fill = null
}
1.3 Stroke property
就是通过数据画出来的线的粗细、颜色等属性。
Series = new ISeries[]
{
new LineSeries<int>
{
Values = new [] { 4, 4, 7, 2, 8 },
Stroke = new SolidColorPaint(SKColors.Blue) { StrokeThickness = 4 },
Fill = null,
GeometryFill = null,
GeometryStroke = null
},
new LineSeries<int>
{
Values = new [] { 7, 5, 3, 2, 6 },
Stroke = new SolidColorPaint(SKColors.Red) { StrokeThickness = 8 },
Fill = null,
GeometryFill = null,
GeometryStroke = null
},
new LineSeries<int>
{
Values = new [] { 4, 2, 5, 3, 9 },
Stroke = new SolidColorPaint(SKColors.Green) { StrokeThickness = 1 },
Fill = null,
GeometryFill = null,
GeometryStroke = null
}
};
1.4 Fill property
填充数据线下面的内容。
Series = new ISeries[]
{
new LineSeries<int>
{
Values = new [] { 4, 4, 7, 2, 8 },
Fill = new SolidColorPaint(SKColors.Blue.WithAlpha(90)),
Stroke = null,
GeometryFill = null,
GeometryStroke = null
},
new LineSeries<int>
{
Values = new [] { 7, 5, 3, 2, 6 },
Fill = new SolidColorPaint(SKColors.Red.WithAlpha(90)),
Stroke = null,
GeometryFill = null,
GeometryStroke = null
},
new LineSeries<int>
{
Values = new [] { 4, 2, 5, 3, 9 },
Fill = new SolidColorPaint(SKColors.Green.WithAlpha(90)),
Stroke = null,
GeometryFill = null,
GeometryStroke = null
}
};
1.5 GeometryFill and GeometryStroke properties
The geometry is the circle shape (by default) that the line series draws for every point, you can customize the fill and stroke of this shape, if none of these properties are set then LiveCharts will create them based on the series position in your series collection and the current theme.
默认是圆形的,可以自定义形状,就是下面这东西。
Series = new ISeries[]
{
new LineSeries<int>
{
Values = new [] { 4, 4, 7, 2, 8 },
Stroke = new SolidColorPaint(SKColors.Blue) { StrokeThickness = 4 },
Fill = null,
GeometryFill = new SolidColorPaint(SKColors.AliceBlue),
GeometryStroke = new SolidColorPaint(SKColors.Gray) { StrokeThickness = 4 }
},
new LineSeries<int>
{
Values = new [] { 7, 5, 3, 2, 6 },
Stroke = new SolidColorPaint(SKColors.Red) { StrokeThickness = 8 },
Fill = null,
GeometryFill = new SolidColorPaint(SKColors.IndianRed),
GeometryStroke = new SolidColorPaint(SKColors.DarkSalmon) { StrokeThickness = 8 }
}
};
1.6 GeometrySize property
就是上面每个点的形状大小
Series = new ISeries[]
{
new LineSeries<int>
{
Values = new [] { 4, 4, 7, 2, 8 },
GeometrySize = 10
},
new LineSeries<int>
{
Values = new [] { 7, 5, 3, 2, 6 },
GeometrySize = 30
}
};
1.7 LineSmoothness property
Determines if the series line is straight or curved, this property is of type
double
and goes from0
to1
any other value will be ignored, where 0 is straight and 1 is the most curved line.决定线是直的还是弯曲的,这个属性值是double类型,值大小从0-1,0是直的,1代表弯的。
Series = new ISeries[]
{
new LineSeries<int>
{
Values = new [] { 5, 4, 7, 3, 8 },
LineSmoothness = 0
},
new LineSeries<int>
{
Values = new [] { 7, 2, 6, 2, 6 },
LineSmoothness = 1
}
};
1.8 EnableNullSplitting property
This property is enabled by default (
true
), it has a performance cost and allows the series to create gaps, when the series finds anull
instance then the series will create a gap.线中间出现缺口
Series = new ISeries[]
{
new LineSeries<int?>
{
Values = new int?[]
{
5,
4,
2,
null,
3,
8,
6
},
LineSmoothness = 0
}
};
1.9 Plotting custom types
You can teach LiveCharts to plot anything, imagine the case where we have an array of the
City
class defined bellow:我们可以教给LiveChart去画任何事情,想象以下我们自定义了一个city类。
public class City
{
public string Name { get; set; }
public double Population { get; set; }
public double LandArea { get; set; }
}
You can register this type globally, this means that every time LiveCharts finds a
City
instance in a chart it will use the mapper we registered, global mappers are unique for a type, if you need to plot multiple properties then you should use local mappers.将其注册成全局的,这样,每次LiveCharts看到City这个数据类型,就会用mapper来注册,如果像哟啊使用多种属性,就需要使用本地mapper了
LiveCharts.Configure(config =>
config
.HasMap<City>((city, point) =>
{
// in this lambda function we take an instance of the City class (see city parameter)
// and the point in the chart for that instance (see point parameter)
// LiveCharts will call this method for every instance of our City class array,
// now we need to populate the point coordinates from our City instance to our point
// in this case we will use the Population property as our primary value (normally the Y coordinate)
point.PrimaryValue = (float)city.Population;
// then the secondary value (normally the X coordinate)
// will be the index of city in our cities array
point.SecondaryValue = point.Context.Index;
// but you can use another property of the city class as the X coordinate
// for example lets use the LandArea property to create a plot that compares
// Population and LandArea in chart:
// point.SecondaryValue = (float)city.LandArea;
})
.HasMap<Foo>(...) // you can register more types here using our fluent syntax
.HasMap<Bar>(...)
);
Now we are ready to plot cities all over our application:
下面开始用
Series = new[]
{
new LineSeries<City>
{
Name = "Population",
TooltipLabelFormatter = point => $"{point.Model.Name} {point.PrimaryValue:N2}M",
Values = new[]
{
new City { Name = "Tokyo", Population = 4, LandArea = 3 },
new City { Name = "New York", Population = 6, LandArea = 4 },
new City { Name = "Seoul", Population = 2, LandArea = 1 },
new City { Name = "Moscow", Population = 8, LandArea = 7 },
new City { Name = "Shanghai", Population = 3, LandArea = 2 },
new City { Name = "Guadalajara", Population = 4, LandArea = 5 }
}
}
};
Alternatively you could create a local mapper that will only work for a specific series, global mappers will be ignored when the series
Mapping
property is not null.或者可以创建一个本地mapper
var cities = new[]
{
new City { Name = "Tokyo", Population = 4, LandArea = 3 },
new City { Name = "New York", Population = 6, LandArea = 4 },
new City { Name = "Seoul", Population = 2, LandArea = 1 },
new City { Name = "Moscow", Population = 8, LandArea = 7 },
new City { Name = "Shanghai", Population = 3, LandArea = 2 },
new City { Name = "Guadalajara", Population = 4, LandArea = 5 }
};
Series = new[]
{
// this series draws the Population property in the Y axis
new LineSeries<City>
{
Name = "Population",
TooltipLabelFormatter = point => $"{point.Model.Name} population: {point.PrimaryValue:N2}M",
Values = cities,
Mapping = (city, point) =>
{
point.PrimaryValue = (float)city.Population;
point.SecondaryValue = point.Context.Index;
}
},
// draws the LandArea property in the Y axis
new LineSeries<City>
{
Name = "Population",
TooltipLabelFormatter = (point) => $"{point.Model.Name} area: {point.PrimaryValue:N2}KM2",
Values = cities,
Mapping = (city, point) =>
{
point.PrimaryValue = (float)city.LandArea;
point.SecondaryValue = point.Context.Index;
}
},
// compares Population (Y) and LandArea (Y)
//new LineSeries<City>
//{
// Name = "Population",
// TooltipLabelFormatter = (point) => $"{point.Model.Name} population: {point.PrimaryValue:N2}M, area: {point.SecondaryValue}KM2",
// Values = cities,
// Mapping = (city, point) =>
// {
// point.PrimaryValue = (float)city.Population;
// point.SecondaryValue = (float)city.LandArea;
// }
//}
};
1.10 Custom geometries
You can use any geometry to represent a point in a line series.
可以使用任和几何形状代替线上面每个点
Series = new List<ISeries>
{
// use the second argument type to specify the geometry to draw for every point
// there are already many predefined geometries in the
// LiveChartsCore.SkiaSharpView.Drawing.Geometries namespace
new LineSeries<double, LiveChartsCore.SkiaSharpView.Drawing.Geometries.RectangleGeometry>
{
Values = new List<double> { 3, 3, -3, -2, -4, -3, -1 },
Fill = null,
LineSmoothness = 1
},
// you can also define your own SVG geometry
new LineSeries<double, MyGeometry>
{
Values = new List<double> { -2, 2, 1, 3, -1, 4, 3 },
Stroke = new SolidColorPaint(SKColors.DarkOliveGreen, 3),
Fill = null,
GeometryStroke = null,
GeometryFill = new SolidColorPaint(SKColors.DarkOliveGreen),
GeometrySize = 40
}
};
1.11 DataPadding
The data padding is the minimum distance from the edges of the series to the axis limits, it is of type
System.Drawing.PointF
both coordinates (X and Y) goes from 0 to 1, where 0 is nothing and 1 is the axis tick an axis tick is the separation between every label or separator (even if they are not visible).If this property is not set, the library will set it according to the series type, take a look at the following samples:
数据距离坐标轴的距离
new LineSeries<double>
{
DataPadding = new System.Drawing.PointF(0, 0),
Values = new ObservableCollection { 2, 1, 3, 5, 3, 4, 6 },
GeometryStroke = null,
GeometryFill = null,
Fill = null
}
But you can remove the padding only from an axis, for example:
也可以将padding从axis去除
new LineSeries<double>
{
DataPadding = new System.Drawing.PointF(0.5f, 0),
Values = new ObservableCollection<double> { 2, 1, 3, 5, 3, 4, 6 },
GeometryStroke = null,
GeometryFill = null,
Fill = null
}
Or you can increase the distance:
或者,增加距离
new LineSeries<double>
{
DataPadding = new System.Drawing.PointF(2, 2),
Values = new ObservableCollection<double> { 2, 1, 3, 5, 3, 4, 6 },
GeometryStroke = null,
GeometryFill = null,
Fill = null
}
二、Axes
The following diagram illustrates an axis and its main components:
下图说明了axis和它的主要组件
xy坐标轴标签,xy轴值之间的间隙大小。
The cartesian chart control has the
XAxes
andYAxes
properties, both of typeIEnumerable<IAxis>
by default when you do not set these properties, they will be an array containing only one element of theAxis
class (new Axis[] { new Axis() }
).笛卡尔表有
XAxes
和YAxes属性,这俩默认都是IEnumerable<IAxis>
类型,它是一个仅仅包含一个Axis类元素的
数组
2.1 Zooming and Panning
Both of these features are directly related to the MaxLimit and MinLimit properties, zooming occurs when the mouse wheel moves or when the pinch gesture occurs, the panning is called when the pointer goes down, moves and then goes up
Zooming is disabled by default, you must set the
ZoomMode
property toX
,Y
orBoth
, normally theX
mode is the most accurate for horizontal series (LineSeries, ColumnSeries), theY
mode for vertical series (RowSeries) and theBoth
mode for Heat or Scatter series.可以通过鼠标滚轮缩放xy轴,默认是不能缩放的,需要设置下
ZoomMode属性的值,比如X、Y或者Both。
X Mode:
When the user interacts with the chart, He/She/* is only moving the chart in the X axis direction, the Y axis range is calculated automatically by the library to fit all the visible points in the X axis.
如果设置
ZoomMode属性的值位X模式,用户只能缩放X轴,Y轴范围根据库中自定义的自动缩放。
<lvc:CartesianChart
Series="{Binding Series}"
TooltipPosition="Hidden"
ZoomMode="X">
</lvc:CartesianChart>
Y Mode:
When the user interacts with the chart, He/She/* is only moving the chart in the Y axis direction, the X axis range is calculated automatically by the library to fit all the visible points in the Y axis.
同理,设置列Y模式,就只能滚动Y轴,x轴自动缩放。
<lvc:CartesianChart
Series="{Binding Series}"
TooltipPosition="Hidden"
ZoomMode="Y">
</lvc:CartesianChart>
Both Mode:
Both axis are moved by the user, this method could lead to the user to get lost in the canvas, you probably need to implement a button to reset the zoom to the data in the chart (settings
MinLimit
andMaxLimit
properties tonull
).xy轴同时缩放。但是最好设置个button用来reset这个缩放。
<lvc:CartesianChart
Series="{Binding Series}"
TooltipPosition="Hidden"
ZoomMode="Both">
</lvc:CartesianChart>
2.2 MaxLimit and MinLimit properties
These properties control the zooming and panning of a chart, both properties are of type of
double?
, you can indicate the visible range of an axis setting these properties. For example, imagine you are plotting aLineSeries
that goes from 0 to 100 in theX
axis, but you only need to show to the user the first 10 points (paging), in this case you could set theMinLimit
property to 0 and theMaxLimit
to 10.设置缩放最大最小步长。
2.3 Clearing the current zooming or panning
Setting
MinLimit
andMaxLimit
properties tonull
will clear the currentzooming
orpanning
, and will let the chart fit the view of the chart to the available data in the chart, the default value of both properties isnull
.将
MinLimit
和MaxLimit属性设置为null就取消缩放了。
2.4 MinStep property
The
Step
defines the interval or distance between every separator and label in the axis, LiveCharts will calculate it automatically based on the chart data and the chart size size, but you can configure the minimum value this property could be, for example in the case where you don't want decimal separations in the axis labels, you could set theMinStep
property to1
, this way, when the calculated step is less that1
the library will force it to be1
.设置坐标系值间隔最小值
2.5 Position property
The axis position property is type
AxisPosition
, it is anenum
containing only 2 options,Start
andEnd
theStart
position places the axis at the bottom for X axes and at the left for Y axes and theEnd
position places the axis at the top for X axes and at the right for Y axes.axis位置属性类型是
AxisPosition,是一个包含两个值的枚举属性--Start
和End,Start
属性会将x轴的值设置在下面,把y轴的值设置在左边,end就是另两边了。
2.6 LabelsPaint and SeparatorsPaint properties
You can set the color, use dashed lines, build gradients for the axis name, labels and separators.
设置axis 名字, 标签 and 分割线的颜色
using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.Painting.Effects;
using SkiaSharp;
namespace ViewModelsSamples.Bars.Basic
{
public class ViewModel
{
public ISeries[] Series { get; set; }
= new ISeries[] { new ColumnSeries<int> { Values = new[] { 2, 5, 4, -2, 4, -3, 5 } } };
public Axis[] XAxes { get; set; }
= new Axis[]
{
new Axis
{
Name = "X Axis",
NamePaint = new SolidColorPaint(SKColors.Black),
LabelsPaint = new SolidColorPaint(SKColors.Blue),
TextSize = 10,
SeparatorsPaint = new SolidColorPaint(SKColors.LightSlateGray) { StrokeThickness = 2 }
}
};
public Axis[] YAxes { get; set; }
= new Axis[]
{
new Axis
{
Name = "Y Axis",
NamePaint = new SolidColorPaint(SKColors.Red),
LabelsPaint = new SolidColorPaint(SKColors.Green),
TextSize = 20,
SeparatorsPaint = new SolidColorPaint(SKColors.LightSlateGray)
{
StrokeThickness = 2,
PathEffect = new DashEffect(new float[] { 3, 3 })
}
}
};
}
}
<lvc:CartesianChart
Series="{Binding Series}"
XAxes="{Binding XAxes}"
YAxes="{Binding YAxes}">
</lvc:CartesianChart>
2.7 Labels vs Labeler properties
There are 2 ways to format and axis labels, using the
Labels
property and using theLabeler
property, you must normally use theLabels
property to indicate names, and theLabeler
property to give format to the current label.The labels property is a collection of string, if this property is not
null
, then the axis label will be pulled from the labels collection, the label is mapped to the chart based on the position of the label and the position of the point, both integers, if the axis requires a label outside the bounds of the labels collection, then the index will be returned as the label, default value is null.可以通过
Labels和Labeler属性格式化axis标签。我们平常用的最多的是Labels去显示names属性,并通过Labeler属性去格式化lable。
Series = new ObservableCollection<ISeries>
{
new ColumnSeries<int>
{
Values = new ObservableCollection<int> { 200, 558, 458, 249 },
}
};
XAxes = new List<Axis>
{
new Axis
{
// Use the labels property to define named labels.
Labels = new string[] { "Anne", "Johnny", "Zac", "Rosa" }
}
};
YAxes = new List<Axis>
{
new Axis
{
// Now the Y axis we will display labels as currency
// LiveCharts provides some common formatters
// in this case we are using the currency formatter.
Labeler = Labelers.Currency
// you could also build your own currency formatter
// for example:
// Labeler = (value) => value.ToString("C")
// But the one that LiveCharts provides creates shorter labels when
// the amount is in millions or trillions
}
};
2.8 LabelsRotation property
Indicates the axis labels rotation in degrees, in the following image we have a rotation of 45 degrees in the Y axis.
标签旋转角度
YAxes = new List<Axis>
{
new Axis
{
LabelsRotation = 45
}
};
2.9 Multiple axes
Both of these properties are collections because the library supports to have more than one axis, the following sample illustrates how to create a chart that uses multiple axes:
多坐标轴显示
三、Tooltips
Tooltips are popups that help the user to read a chart as the pointer moves.
提示框是个弹出窗口,帮助我们在移动鼠标时读取鼠标指定的图表的数据。
3.1 TooltipPosition property
You can place a tooltip at
Top
,Bottom
,Left
,Right
,Center
orHidden
positions, for now tooltips for thePieChart
class only support theCenter
position, default value isTop
.Notice the
Hidden
position will disable tooltips in a chart.tooltip放置位置可以是上、下、左、右、中、隐藏,饼状图只支持中间,其他的默认时放在上面,注意:如果设置成隐藏将会使tooltip不能使用在图表中。
3.2 TooltipFindingStrategy property
Every point drawn by the library defines a HoverArea, it defines an area in the chart that "triggers" the point, it is specially important to fire tooltips, a point will be included in a tooltip when the hover area was triggered by the pointer position.
The
TooltipFindingStrategy
property determines the hover area planes (X or Y) that a chart will use to trigger theHoverArea
instances. In a chart, the following options are available:动态库中定义了个悬停区域,用于触发图表中的点,
TooltipFindingStrategy
属性决定悬停区域显示X轴值还是Y轴值,这个计划会用于触发悬停区域实例。下面使可选属性值:CompareAll: Selects all the points whose hover area contain the pointer position.
CompareAll可以同时显示X和Y轴数据。
CompareOnlyX: Selects all the points whose hover area contain the pointer position, but it ignores the Y plane.
只显示X轴数据。
CompareOnlyY: Selects all the points whose hover area contain the pointer position, but it ignores the X plane.
只显示Y轴数据。
<lvc:CartesianChart
Series="{Binding Series}"
TooltipFindingStrategy="CompareOnlyX">
</lvc:CartesianChart>
<!--只显示X值-->
XY轴值都显示
只显示X轴值
只显示Y轴值
3.3 Tooltip point text
给显示的XY轴值加上代表的数值含义
You can define the text the tooltip will display for a given point, using the
Series.TooltipLabelFormatter
property, this property is of typeFunc<ChartPoint, string>
this means that is is a function, that takes a point as parameter and returns a string, the point will be injected by LiveCharts in this function to get a string out of it when it requires to build the text for a point in a tooltip, the injected point will be different as the user moves the pointer over the user interface.By default the library already defines a default
TooltipLabelFormatter
for every series, all the series have a different formatter, but generally the default value uses theSeries.Name
and theChartPoint.PrimaryValue
properties, the following code snippet illustrates how to build a custom tooltip formatter.通过
Series.TooltipLabelFormatter属性给要显示的点加上文字描述。这个属性是个Func<ChartPoint, string>类型,这是个方法,放进去point,返回一个string。
默认情况下,框架帮每一个series定义了这个属性。全部的series都有一个不同的formatter,但是总体上默认的值是使用Series的Name属性和ChartPoint的PrimaryValue属性,下面用示例演示下怎么自定义tooltip formatter。
new LineSeries<double>
{
Name = "Sales",
Values = new ObservableCollection<double> { 200, 558, 458 },
// 按照下面的格式进行格式化的话
// 当鼠标移动到点200的时候,tooltip会显示
// Sales: 200
TooltipLabelFormatter =
(chartPoint) => $"{chartPoint.Context.Series.Name}: {chartPoint.PrimaryValue}"
},
new ColumnSeries<double>
{
Name = "Sales 2",
Values = new ObservableCollection<double> { 250, 350, 240 },
// 使用货币格式化来显示初始值
// 结果: Sales 2: $200.00
TooltipLabelFormatter =
(chartPoint) => $"{chartPoint.Context.Series.Name}: {chartPoint.PrimaryValue:C2}"
},
new StepLineSeries<ObservablePoint>
{
Name = "Average",
Values = new ObservableCollection<ObservablePoint>
{
new ObservablePoint(10, 5),
new ObservablePoint(5, 8)
},
// 同时显示xy轴
// 结果: Average: 10, 5
TooltipLabelFormatter =
(chartPoint) => $"{chartPoint.Context.Series.Name}: {chartPoint.SecondaryValue}, {chartPoint.PrimaryValue}"
},
new ColumnSeries<ObservablePoint>
{
Values = new ObservableCollection<double> { 250, 350, 240 },
// 任和东西都可以代替键部分
// result: Sales at this moment: $200.00
TooltipLabelFormatter =
(chartPoint) => $"Sales at this moment: {chartPoint.PrimaryValue:C2}"
}
3.4 Styling tooltips
提示框的样式,最简单的就是字体、颜色、位置等。
<lvc:CartesianChart
Series="{Binding Series}"
TooltipPosition="Left"
TooltipFontFamily="Courier New"
TooltipFontSize="25"
TooltipTextBrush="#f2f4c3"
TooltipBackground="#480032">
</lvc:CartesianChart>
3.5 Custom template
自定义模板
<UserControl x:Class="WPFSample.General.TemplatedTooltips.View" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF" xmlns:vms="clr-namespace:ViewModelsSamples.General.TemplatedTooltips;assembly=ViewModelsSamples" xmlns:ctx="clr-namespace:LiveChartsCore.Kernel;assembly=LiveChartsCore"> <UserControl.DataContext> <vms:ViewModel/> </UserControl.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> </Grid.RowDefinitions> <lvc:CartesianChart Grid.Row="0" Series="{Binding Series}" TooltipPosition="Top" > <lvc:CartesianChart.TooltipTemplate> <DataTemplate> <Border Background="#303030"> <ItemsControl ItemsSource="{Binding Points, RelativeSource={RelativeSource AncestorType=lvc:DefaultTooltip}}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate DataType="{x:Type ctx:ChartPoint}"> <Border Padding="7 5"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding AsTooltipString}" Margin="0 0 8 0" Foreground="AntiqueWhite" /> <lvc:MotionCanvas Margin="0 0 8 0" PaintTasks="{Binding Context.Series.CanvasSchedule.PaintSchedules}" Width="{Binding Context.Series.CanvasSchedule.Width}" Height="{Binding Context.Series.CanvasSchedule.Height}" VerticalAlignment="Center"/> </StackPanel> </Border> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Border> </DataTemplate> </lvc:CartesianChart.TooltipTemplate> </lvc:CartesianChart> </Grid> </UserControl>
四、Legends
A legend is a visual element that displays a list with the name, stroke and fills of the series in a chart:
图例是一个用来显示图表中数据的名字、画笔等属性的可视化元素
You can place a legend at
Top
,Bottom
,Left
,Right
orHidden
positions, notice theHidden
position will disable legends in a chart, default value isHidden
.图例可以放在上、下、左、右位置或者隐藏,注意默认是隐藏的
<lvc:CartesianChart
Series="{Binding Series}"
LegendPosition="Top">
</lvc:CartesianChart>
<lvc:CartesianChart
Series="{Binding Series}"
LegendPosition="Bottom">
</lvc:CartesianChart>
<lvc:CartesianChart
Series="{Binding Series}"
LegendPosition="Left">
</lvc:CartesianChart>
<lvc:CartesianChart
Series="{Binding Series}"
LegendPosition="Right">
</lvc:CartesianChart>
<lvc:CartesianChart
Series="{Binding Series}"
LegendPosition="Hidden">
</lvc:CartesianChart>
4.1 styling legends
A chart exposes many properties to quickly style a legend:
可以通过chart暴露的多个属性快速构建一个快速的style
<lvc:CartesianChart
Series="{Binding Series}"
LegendPosition="Left"
LegendFontFamily="Courier New"
LegendFontSize="25"
LegendTextBrush="#f2f4c3"
LegendBackground="#480032">
</lvc:CartesianChart>
4.2 Custom template
<lvc:CartesianChart Grid.Row="0" Series="{Binding Series}" LegendPosition="Right" >
<lvc:CartesianChart.LegendTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Series, RelativeSource={RelativeSource AncestorType=lvc:DefaultLegend}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Center" VerticalAlignment="Center"
Orientation="{Binding Orientation, RelativeSource={RelativeSource AncestorType=lvc:DefaultLegend}}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Padding="15 4" Background="#F5F5DC">
<StackPanel Orientation="Horizontal">
<TextBlock
Text="{Binding Name}"
VerticalAlignment="Center"/>
<lvc:MotionCanvas
Margin="8 0 0 0"
PaintTasks="{Binding CanvasSchedule.PaintSchedules}"
Width="{Binding CanvasSchedule.Width}"
Height="{Binding CanvasSchedule.Height}"
VerticalAlignment="Center"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</lvc:CartesianChart.LegendTemplate>
</lvc:CartesianChart>