接下來要談到的是使用 Series<TModel, TVisual, TLabel, TDrawingContext>.Mapping 屬性來做資料對應。
前言
LiveCharts 裡有兩種資料對應方式,其中一種就是使用 Mapper,過程很簡單,設定 Series<TModel, TVisual, TLabel, TDrawingContext>.Mapping Property 即可。
Mapping 屬性的型別是一個 Func<TModel, int, Coordinate> ,這表示傳入兩個參數 (1) 自訂的資料型別 (2) 資料在集合的索引,然後回傳 Coordinate。
準備工作(1) 圖表的基本 View Model
這次我將圖表直接繫結的 View Model 獨立設計,後面 MainViewModel 會引入這個型別。
public class ChartCommonViewModel : NotifyPropertyBase
{
private ObservableCollection<ISeries> _series;
private ObservableCollection<Axis> _xAxes;
private ObservableCollection<Axis> _yAxes;
public ObservableCollection<ISeries> Series
{
get => _series;
set => SetProperty(ref _series, value);
}
public ObservableCollection<Axis> XAxes
{
get => _xAxes;
set => SetProperty(ref _xAxes, value);
}
public ObservableCollection<Axis> YAxes
{
get => _yAxes;
set => SetProperty(ref _yAxes, value);
}
private SolidColorPaint _toolTipTextPaint;
public SolidColorPaint ToolTipTextPaint
{
get => _toolTipTextPaint;
set => SetProperty(ref _toolTipTextPaint, value);
}
public ChartCommonViewModel()
{
Series = new ObservableCollection<ISeries>();
XAxes = new ObservableCollection<Axis>();
YAxes = new ObservableCollection<Axis>();
}
}
準備工作 (2) 單筆資料的 View Model
public class PersonViewModel : NotifyPropertyBase
{
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);
}
}
完成 MainViewModel
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},
new PersonViewModel { Name = "索隆" , Score = 79},
new PersonViewModel { Name = "香吉士" , Score = 58},
new PersonViewModel { Name = "娜美" , Score = 82},
new PersonViewModel { Name = "羅賓" , Score = 100},
new PersonViewModel { Name = "喬巴" , Score = 43},
};
}
private void CreateTextPaint()
{
Chart.ToolTipTextPaint = new SolidColorPaint
{
Color = SKColors.Black,
SKTypeface = SKFontManager.Default.MatchFamily("新細明體"),
};
}
private void AddSeries()
{
Chart.Series.Add(
new ColumnSeries<PersonViewModel>
{
Mapping = (person, index) => new Coordinate(index, person.Score),
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);
}
}
主要關注的程式碼在 AddSeries() 方法內部:
private void AddSeries()
{
Chart.Series.Add(
new ColumnSeries<PersonModel>
{
Mapping = (person, index) => new Coordinate(index, person.Score),
Values = People,
});
}
加入一段長條圖的資料,設定他的X軸資料對應 index,Y軸資料對應 PersnViewModel.Score 屬性。
Y 軸的設定相當簡單,因為我們要顯示的就是分數,所以直接用 Labeler 屬性 (這是個 Func<double,string>),把每一筆 PersnViewModel.Score 透過他轉成字串顯示:
private void AddYAxes()
{
Chart.YAxes.Add(
new Axis
{
Labeler = value => $"{value} 分",
LabelsPaint = new SolidColorPaint
{
Color = SKColors.Black,
SKTypeface = SKFontManager.Default.MatchFamily("新細明體"),
},
});
}
X 軸就麻煩了些,因為 Mapping 取得的 X 軸的值是 index,但我們並沒有想要顯示 0,1,2,3,4 ….,而是要顯示 PersonViewModel.Name,所以要做點手腳:
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("新細明體"),
},
});
}
畫面很簡單就長這樣:
<Window x:Class="LiveChartsV2Sample003.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:LiveChartsV2Sample003"
xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext >
<local:MainViewModel />
</Window.DataContext>
<Grid>
<lvc:CartesianChart Series="{Binding Chart.Series}"
XAxes="{Binding Chart.XAxes}"
YAxes="{Binding Chart.YAxes}"
TooltipTextPaint="{Binding Chart.ToolTipTextPaint}">
</lvc:CartesianChart>
</Grid>
</Window>
順帶一提,TooltipTextPaint 屬性可以用來設定 ToolTip 的顯示字型,因為用中文,所以需要設定此屬性讓 ToolTip 顯示正確的文字。
本篇文章的範例在此。