LiveCharts文檔-3開始-3類型和設置
類型和設置
這一部分非常的重要,涉及到LiveCharts的基本構成單元的介紹
LiveChart可以繪制任何類型,甚至是自定義的類型,且不丟失強類型語言的好處,原理很簡單,當你傳遞一個泛型集合的時候,LiveChart會拉取X和Y值(笛卡爾Chart),你不需要定義每個類型來繪制它。庫已經知道怎么繪制,double,int,decimal,short ,float,long還有其他特別設計的類型,ObservableCollection,ObservablePoint,ScatterPoint,DateTimePoint,HeatPoint,OHLPoint,PolarPoint.所以的這些類型都可以在屬性改變的時候通知chart進行更新,下面的例子就使用了這些類型,你也可以自己定義自己需要的類型。
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)
};
你可以注意到,chart總是使用X,Y坐標來繪制(笛卡爾坐標系),但是一個組double,int,long值庫也能夠繪制是怎么一回事?
很簡單,X是這組數組當中的index,Y就是你傳遞的值。當然,這只是你使用橫向序列的時候是這樣,如果你使用縱向序列,那么X就是傳遞的值,Y就是Index。
var myValues = new LiveCharts.ChartValues<double>
{
10, //index 0
6, //index 1
9, //index 2
2, //index 3
7 //index 4
}
實際的坐標是:
已經定義了拉取坐標的配置:
橫向坐標:
new CartesianMapper<double>()
.X((value, index) => index) //use the index as X
.Y((value, index) => value) //use the value as Y
縱向坐標:
new CartesianMapper<double>()
.X((value, index) => value) //use the value as X
.Y((value, index) => index) //use the index as Y
X和Y只是對於笛卡爾Chart有必要,但是當你想要繪制一個雷達圖(半徑和角度)或者金融Chart的時候,該怎么配置?所以我創建了一個 Mappers類型,這個類型會返回一個正確mapper的實例,有很多選項,Xy,Financial,Bubble和Polar,上面的mappers將會被取代為:
Mappers.Xy<double>()
.X((value, index) => index) //use the index as X
.Y((value, index) => value) //use the value as Y
下面是多重mappers,這些是根據你的情況來設定的。
//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);
你可以通過多種方式設定mappers:
1.Global級別
這種方法在你的應用程序級別保存設置,每次LiveCharts檢查Chart Values實例中的類型的時候,它都會使用這個mapper,除非SeriesCollection mapper和Series mapper是null。
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
另外一個例子就是自定義類型,ObseravableCollection類只包含兩個屬性,X和Y,請注意這次我給橫向和縱向使用了同樣的設置,並沒有傳遞第二個參數。
For<ObservablePoint>(Mappers.Xy<ObservablePoint>()
.X((value, index) => value.X)
.Y(value => value.Y));`
如果這個還不是很明白,可以去源碼里找到更多細節。
2.Series Collection級別
但當你定義一個Series Collection的時候,你也可以傳遞一個默認的配置,這個配置將會覆蓋掉全局配置,除非Series級別的配置是null。
var mapper = Mappers.Xy<MyClass>().X(v => v.XProp).Y(v => v.YProp);
var seriesCollection = new SeriesCollection(mapper);
myChart.SeriesCollection = seriesCollection;
3.特定的Series級別
最后,如果只是為了設定一個Series,你可以定義一個特定的mapper用於它,這個配置會覆蓋掉Global和Series Collection級別的配置。
var mapper = Mappers.Xy<MyClass>().X(v => v.XProp).Y(v => v.YProp);
var pieSeries = new PieSeries(mapper);
通知Chart自動更新
你可以實現IObservableChartPoint接口,從而實現當自定義類型的屬性改變的時候,Chart會自動進行更新。下一個例子你將會看到 ObservableValue類型的定義,看看它是怎么在Value改變的時候通知Chart改變的。這個很好理解,你只需要每次在設定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();
}
}
本節內容完