Search code examples
c#wpflivecharts

Create a WPF C# chart with Live Chart


I Use Live Chart. SeriesCollection passes a Line Series in which Values = Chart Values. In xaml in Binding, I pass SeriesCollection. I understand that only y-points are transmitted (I do not change anything by default). How to transmit x points? Tried in ChartValue by index, swears that the index is empty. And even if you initially set the size of Chart Values, the cells that are not filled on the chart are filled as Y = 0. Please help, been three days sitting on it.

GenerateChart.cs:

public ChartValues<double> Points { get; set; }
        double[] arraySeries = new double[30];
        double[] array = new double[20];
        public LineSeries GenerateSeries(string axis)
        {
            Random randomSeries = new Random();
            ChartValues<double> series = new ChartValues<double>(new double[20]);

            if (axis == "Y")
            {
                for (int i = 0; i < 5; i++)
                {
                    double randomValue = randomSeries.Next(1, 20);
                    if (!array.Contains(randomValue))
                    {
                        array[i] = randomValue;
                    }
                    else
                    {
                        i--;
                    }
                }

                for (int i = 0; i < 5; i++)
                {
                    double randomValue = randomSeries.Next(1, 20);
                    if (!arraySeries.Contains(randomValue))
                    {
                        int index = Convert.ToInt32(array[i]);
                        arraySeries[index] = randomValue;
                    }
                    else
                    {
                        i--;
                    }
                }

                for (int i = 0; i < 20; i++)
                {
                    if (arraySeries[i] != 0)
                    {
                        series.Insert(i, arraySeries[i]);
                    }
                }
                //series.AddRange(arraySeries);

            }
            Points = series;
            var testSeries = new LineSeries
            {
                Title = "Test",
                Values = series
            };

            return testSeries;
        }

RandomSeries.cs:

public SeriesCollection Series { get; private set; }

        public SeriesCollection SeriesX { get; private set; }

        public ChartValues<double> Points { get; private set; }
        double[] arraySeries = new double[30];
        double[] array = new double[20];
        public SeriesCollection BuidChart()
        {
            Random randomSeries = new Random();
            var generateChart = new GenerateChart();

            Series = new SeriesCollection 
            {
                generateChart.GenerateSeries("Y")
            };
            Points = generateChart.Points;
            return Series;
        } 

ModelView.cs:

public SeriesCollection SeriesCollection { get; set; }
        public ChartValues<double> Points { get; set; }
        public RandomSeries randomSeries;
        public Func<double, string> YFormatter { get; set; }
        public string[] Labels { get; set; }
        public SeriesCollection SeriesCollectionX { get; set; }
        public void BuildFunction()
        {
            //Points.Clear();
            //SeriesCollection.Clear();
            randomSeries = new RandomSeries();
            SeriesCollection = new SeriesCollection();
            Points = new ChartValues<double>();
            SeriesCollection.AddRange(randomSeries.BuidChart());
            //Points.AddRange(randomSeries.Points);
            //SeriesCollection.AddRange(randomSeries.BuidChart());
            //Points.AddRange(randomSeries.Points);
            Labels = new[] { "Jan", "Feb", "Mar", "Apr", "May", "Jan1", "Feb1", "Mar1", "Apr1", "May1" };
        }

MainWindow.xaml:

<Window.DataContext>
        <local:ModelView/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="257*"/>
            <ColumnDefinition Width="536*"/>
        </Grid.ColumnDefinitions>
        <lvc:CartesianChart Series="{Binding SeriesCollection}" LegendLocation="Right" Grid.ColumnSpan="2" Margin="0,0,-0.4,0" >
            <!--<lvc:CartesianChart.AxisY>
                <lvc:Axis Title="Y" LabelFormatter="{Binding YFormatter}"></lvc:Axis>
            </lvc:CartesianChart.AxisY>-->
            <lvc:CartesianChart.AxisX>
                <lvc:Axis Title="X" Labels="{Binding Labels}"></lvc:Axis>
            </lvc:CartesianChart.AxisX>
        </lvc:CartesianChart>
    </Grid>

Result program: enter image description here


Solution

  • Ok in LiveChart there is possiblity to use ObservablePoint which represent X,Y position in the chart.

    You need to add proper namespace to use these

    using LiveCharts.Defaults;
    

    I modfied two things in your Function, first I change definition and initialization of to ChartValues to by empty and typeof of ObservablePoint, so later we will dynamic fill these. You need also to change Points object to be type of ObservablePoint

    ChartValues<ObservablePoint> series = new ChartValues<ObservablePoint>();
    

    And also modified the filling of these series object to add only non-zero:

    for (int i = 0; i < 20; i++)
    {
        if (arraySeries[i] != 0)
        {
            series.Add(new ObservablePoint(i, arraySeries[i]));
        }
     }
    

    It will not draw zero-y-point between non-zero.