LiveCharts可以绘制任何类型,甚至包括用户定义的类型,而不会丢失强类型语言的美观。这个概念很简单:传递通用值的集合,然后LiveCharts需要一个函数来提取X和Y(如果它是笛卡尔图表)。您也不需要定义每种类型来绘制它。
该库已经知道如何绘制double,int,decimal,short,float,long以及其他一些特殊设计的类:ObservableValue, ObservablePoint, ScatterPoint, DateTimePoint, HeatPoint, OHLCPoint, PolarPoint。所有这些类都会通知图表在属性更改时进行更新。本网站中的示例使用这些对象。您可以随时定义自己的类型。
var doubleValues = new ChartValues<double> { 1, 2 ,3 };
var intValues = new ChartValues<int> { 1, 2 ,3 };
//the observable value class is really helpful, it notifies the chart to update
//every time the ObservableValue.Value property changes
var observableValues = new ChartValues<LiveCharts.Defaults.ObservableValue>
{
new LiveCharts.Defaults.ObservableValue(1), //initializes Value property as 1
new LiveCharts.Defaults.ObservableValue(2),
new LiveCharts.Defaults.ObservableValue(3)
};
注意,图表始终使用X和Y坐标
X是数组中值的索引,Y是您传递的值,仅当您使用水平系列时才是正确的,如果您使用垂直系列,则X是值,而Y是索引
var myValues = new LiveCharts.ChartValues<double>
{
10, //index 0
6, //index 1
9, //index 2
2, //index 3
7 //index 4
}
并且已经定义的配置可以
For Horizontal Series
new CartesianMapper<double>()
.X((value, index) => index) //use the index as X
.Y((value, index) => value) //use the value as Y
For Vertical Series
new CartesianMapper<double>()
.X((value, index) => value) //use the value as X
.Y((value, index) => index) //use the index as Y
X and Y is only necessary for Cartesian charts, but how about if you need to configure a polar chart (radius and angle) or a financial series, because my memory is really bad I created a reminder, the Mappers class, this class returns a new instance of the correct mapper, it has many options, Xy, Financial, Bubble and Polar, the mappers above can be replaced with:
Mappers.Xy<double>()
.X((value, index) => index) //use the index as X
.Y((value, index) => value) //use the value as Y
这是一些带有多个映射器的示例
//X and Y
var mapper = Mappers.Xy<ObservablePoint>() //in this case value is of type <ObservablePoint>
.X(value => value.X) //use the X property as X
.Y(value => value.Y); //use the Y property as Y
//X, Y and Weight
var mapper = Mappers.Bubble<BubblePoint>()
.X(value => value.X)
.Y(value => value.Y)
.Weight(value => value.Weight);
//Angle and Radius
var mapper = Mappers.Polar<PolarPoint>()
.Radius(value => value.Radius) //use the radius property as radius for the plotting
.Angle(value => value.Angle); //use the angle property as angle for the plotting
//Open, High, Low and Close
var mapper = Mappers.Financial<OhlcPoint>()
.X((value, index) => index)
.Open(value => value.Open)
.High(value => value.High)
.Low(value => value.Low)
.Close(value => value.Close);
全局定义
当LiveCharts每次在Chart Values实例中检测到此类型时,此方法都会在您的应用程序级别保存配置,仅当SeriesCollection映射器和Series映射器为null时,它将使用此映射器。
VAR mapper1 = 映射器。Xy ()
var mapper1 = Mappers.Xy<int>()
.X((value, index) => index)
.Y(value => value);
LiveCharts.Charting.For<int>(mapper1, SeriesOrientation.Horizontal); //when horizontal
var mapper2 = Mappers.Xy<int>()
.X(value => value) //use the value (int) as X
.Y((value, index) => index);
LiveCharts.Charting.For<int>(mapper2, SeriesOrientation.Vertical); //when vertical
用自定义类的另一个示例ObservablePoint类仅包含X和Y两个属性,这也请注意,这次我在水平和垂直方向上使用了相同的配置,而没有传递第二个参数(方向)
For<ObservablePoint>(Mappers.Xy<ObservablePoint>()
.X((value, index) => value.X)
.Y(value => value.Y));
在系列级别
当您定义Series集合实例时,您还可以传递默认配置,该配置将覆盖全局配置,并且仅在Series配置为null时设置。
var mapper = Mappers.Xy<MyClass>().X(v => v.XProp).Y(v => v.YProp);
var seriesCollection = new SeriesCollection(mapper);
myChart.SeriesCollection = seriesCollection;
特定系列
var mapper = Mappers.Xy<MyClass>().X(v => v.XProp).Y(v => v.YProp);
var pieSeries = new PieSeries(mapper);
图表自动更新
实现IObservableChartPoint,因此当自定义类型的属性更改时,图表将自动更新,在下一个示例中,您将看到ObservableValue类的定义,该类将在Value属性更改时通知图表更新,这个概念确实是很简单,您只需在每次设置Value属性时都调用PointChanged事件。
public class ObservableValue : IObservableChartPoint
{
private double _value;
public ObservableValue()
{
}
public ObservableValue(double value)
{
Value = value;
}
public event Action PointChanged;
public double Value
{
get { return _value; }
set
{
_value = value;
OnPointChanged();
}
}
protected void OnPointChanged()
{
if (PointChanged != null) PointChanged.Invoke();
}
}