I have a project where I have a charting area. I have choosen LiveCharts ( http://lvcharts.net ) for that matter.
So far so good, the charting works with databinding when added in xaml:
<UserControl x:Class="Work_Task_Planner_Sheduler.Views.TeamTaskProgressChartView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Work_Task_Planner_Sheduler.Views"
xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<lvc:CartesianChart x:Name="TeamTaskProgressChartComponent">
<lvc:CartesianChart.Series>
<lvc:LineSeries Title="Julian" Values="{Binding Taskprogress_julian}" />
</lvc:CartesianChart.Series>
<lvc:CartesianChart.AxisX>
<lvc:Axis Title="Time"></lvc:Axis>
</lvc:CartesianChart.AxisX>
<lvc:CartesianChart.AxisY>
<lvc:Axis Title="TaskProgress"></lvc:Axis>
</lvc:CartesianChart.AxisY>
</lvc:CartesianChart>
</Grid>
</UserControl>
The issue is: The Line series is hardcoded in xaml. Who knows if the team gets bigger/smaller over time or the team members change. Therefore I want to create the line series at runtime.
This is what I have so far, unfortunately the series stays empty:
CartesianChart chart = this.TeamTaskProgressChartComponent;
foreach(string user in TeamMembers)
{
LineSeries lineseries = new LineSeries();
string title = user.Split('.')[0];
lineseries.Title = title;
Binding databinding = new Binding();
databinding.Source =
Datarefresh.mainWindow.mainViewModel.TeamTaskProgressChartViewModel.TaskProgressCounts;
DependencyProperty LineSeriesProperty = DependencyProperty.Register(title+"Property", typeof(int), typeof(LineSeries), new PropertyMetadata(0));
lineseries.SetBinding(LineSeriesProperty, databinding);
chart.series.Add(lineseries);
}
Actually the Process is quite Simple:
Create a Series collation. IMPORTANT: The series collection must be initialized in the constructor so that it is ready when the chart loads:
public class TeamTicketResolveChartViewModel
{
public SeriesCollection ChartSeries { get; set; }
public string[] TicketResolveLabels { get; set; }
public TeamTicketResolveChartViewModel()
{
ChartSeries = new SeriesCollection();
foreach (string user in TeamMembers.ServiceDesk)
{
LineSeries lineseries = new LineSeries();
string title = user.Split('.')[0];
lineseries.Title = title;
ChartSeries.Add(lineseries);
}
}
// other functions
}
In xaml, bind the chart to the series Collection:
<lvc:CartesianChart x:Name="TeamTicketResolveChartComponent" Series="{Binding ChartSeries}" />
Now updating the Chart Data will work as intended:
public void LoadChartData2(List<List<(DateTime time, int resolved)>> input)
{
for (int i = 0; i < input.Count; i++)
{
ChartSeries[i].Values = new ChartValues<int>(input[i].Select(c => c.resolved));
}
DateTime[] dates = input[0].Select(c => c.time).ToArray();
List<string> labels = new List<string>();
foreach (DateTime time in dates) labels.Add(time.ToString("HH:mm:ss"));
TicketResolveLabels = labels.ToArray();
}
public void AddChartPoint(List<List<(DateTime time, int resolved)>> input)
{
// Chartseries[i].values.Add()
}