除了使用 Mapping property,LiveChart 提供了另一種資料對應的方式 – 透過實作 IChartEntity interface。
實作 IChartEntity
承上篇文章的 PersonViewModel,加入對於 IChartEntity interface 的實作,這邊為了方便說明,多加了一個 Index property:
public class PersonViewModel : NotifyPropertyBase, IChartEntity
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
private int _score;
public int Score
{
get => _score;
set => SetProperty(ref _score, value);
}
private int _index;
public int Index
{
get => _index;
set => SetProperty(ref _index, value);
}
public ChartEntityMetaData MetaData
{
get; set;
}
public Coordinate Coordinate
{
get; set;
}
protected override void OnPropertyChanged(string propertyName)
{
Coordinate = new Coordinate(Index, Score);
base.OnPropertyChanged(propertyName);
}
}
以下兩個屬性來自於 IChartEntity interface,你會發現沒做甚麼特別的事情 (因為有了 Index 屬性可以當作 X 軸的座標定義):
public ChartEntityMetaData MetaData
{
get; set;
}
public Coordinate Coordinate
{
get; set;
}
接著 override NotifyPropertyBase.OnPropertyChanged 方法,當屬性值變更的時候重新產生 Coordinate,如果要寫得更精確一些就加上屬性名稱的判斷,也就是只有當 Index 和 Score 這兩個決定 X/Y 軸資訊的屬性變更時才重新定義 Coordinate。
protected override void OnPropertyChanged(string propertyName)
{
Coordinate = new Coordinate(Index, Score);
base.OnPropertyChanged(propertyName);
}
回到 MainViewModel
當資料來源實作了 IChartEntity interface,就不需要設定 Series 裡的 Mapping property:
public class MainViewModel : NotifyPropertyBase
{
private ObservableCollection<PersonViewModel> _people;
public ObservableCollection<PersonViewModel> People
{
get => _people;
set => SetProperty(ref _people, value);
}
public MainViewModel()
{
InitialData();
Chart = new ChartCommonViewModel();
AddSeries();
AddXAxes();
AddYAxes();
CreateTextPaint();
}
private void InitialData()
{
People = new ObservableCollection<PersonViewModel>()
{
new PersonViewModel { Name = "魯夫" , Score = 98, Index=0},
new PersonViewModel { Name = "索隆" , Score = 79, Index=1},
new PersonViewModel { Name = "香吉士" , Score = 58, Index=2},
new PersonViewModel { Name = "娜美" , Score = 82, Index=3},
new PersonViewModel { Name = "羅賓" , Score = 100, Index=4},
new PersonViewModel { Name = "喬巴" , Score = 43, Index=5},
};
}
private void CreateTextPaint()
{
Chart.ToolTipTextPaint = new SolidColorPaint
{
Color = SKColors.Black,
SKTypeface = SKFontManager.Default.MatchFamily("新細明體"),
};
}
private void AddSeries()
{
Chart.Series.Add(
new ColumnSeries<PersonViewModel>
{
Values = People,
});
}
private void AddXAxes()
{
Chart.XAxes.Add(
new Axis
{
Labels = new ObservableCollection<string>(People.Select(x => x.Name)),
LabelsPaint = new SolidColorPaint
{
Color = SKColors.Black,
SKTypeface = SKFontManager.Default.MatchFamily("新細明體"),
},
});
}
private void AddYAxes()
{
Chart.YAxes.Add(
new Axis
{
Labeler = value => $"{value} 分",
LabelsPaint = new SolidColorPaint
{
Color = SKColors.Black,
SKTypeface = SKFontManager.Default.MatchFamily("新細明體"),
},
});
}
private ChartCommonViewModel _chart;
public ChartCommonViewModel Chart
{
get => _chart;
set => SetProperty(ref _chart, value);
}
}
其餘的部分就和前一篇一樣了,完整範例可以參考我的github。