Search code examples
c#wpflivecharts

LiveCharts Cartesian Mapping and Configuration with custom Labels


I have plotted the Cartesian chart using X and Y values, to mimic step chart (x values are not consistent). Is it possible to add custom x Labels for each step changed in Y value? Or similar labels like in a bar chart.

 var values = new ChartValues<Point>();

Loop:
    var point = new Point() { X = entry.DailyXFrom, Y = entry.YValue };

    values.Add(point);
    point = new Point() { X = entry.DailyXTo, Y = entry.YValue };
    values.Add(point);
    tempLabels.Add(entry.DailyVolume.ToString());


            seriesCollectionDaily = new SeriesCollection
                      {
                        new LineSeries
                        {
                          Configuration = new CartesianMapper<Point>()
                            .X(point => point.X) 
                            .Y(point => point.Y)
                            ,
                          Fill = Brushes.Transparent,
                          Title = "Series",
                          Values = values,
                          PointGeometry = null,
                          LineSmoothness = 0

                        }
                    };
 XAxis.Separator.IsEnabled = true;
 XAxis.Labels = tempLabels.ToArray();
chart.DataContext = this;


 <lvc:CartesianChart Name="chart"  Grid.Row="2" Grid.ColumnSpan="2" Series="{Binding seriesCollectionDaily }" >
                    <lvc:CartesianChart.AxisX >
                        <lvc:Axis Name="XAxis" Title=""   LabelsRotation="0" Foreground="Black" >
                            <lvc:Axis.Separator>
                                <lvc:Separator Name="LabelSeparator"></lvc:Separator>
                            </lvc:Axis.Separator>
                        </lvc:Axis>
                    </lvc:CartesianChart.AxisX>
 </lvc:CartesianChart>

What I got: enter image description here

This is what I'm trying to achieve. Is it possible? enter image description here


Solution

  • You can add sections to your chart axis.

    To draw vertical sections you have to define a SectionsCollection of AxisSection items and bind it to Axis.Sections of the x-axis.
    By setting AxisSection.Value you can define the position on the axis. Use AxisSection.SectionWidth to define the width of the section. The default is 1, which draws a simple stroke when AxisSection.StrokeThickness is set.

    The following example uses StepLineSeries to plot a step chart. To give an example, it shows two vertical lines placed at the corresponding x-value: a simple line (SectionWidth = 1) and a section where SectionWidth > 1 (e.g., to highlight a range):

    enter image description here

    Data Model

    public class DataModel : INotifyPropertyChanged
    {
      public DataModel()
      {
        this.SeriesCollection = new SeriesCollection
        {
          new StepLineSeries()
          {
            Configuration = new CartesianMapper<ObservablePoint>()
              .X(point => point.X)
              .Y(point => point.Y)
              .Stroke(point => point.Y > 0.3 ? Brushes.Red : Brushes.LightGreen),
            Values = new ChartValues<ObservablePoint>
            {
              new ObservablePoint(0, 5),
              new ObservablePoint(20, 0),
              new ObservablePoint(30, 5),
              new ObservablePoint(40, 0),
              new ObservablePoint(80, 5),
            }
          }
        };
    
        // Add two sections at x=20 and x=30
        this.SectionsCollection = new SectionsCollection()
        {
          new AxisSection()
          {
            Value = 20,
            Stroke = Brushes.Red,
            StrokeThickness = 1
          },
          new AxisSection()
          {
            Value = 30,
            SectionWidth = 50,
            Stroke = Brushes.Red,
            StrokeThickness = 1
          }
        };
      }
    
      public Func<double, string> LabelFormatter => value => $"{value}ms";
      public SeriesCollection SeriesCollection { get; set; }
      public SectionsCollection SectionsCollection { get; set; }
    
      public event PropertyChangedEventHandler PropertyChanged;
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    

    Chart View

    <Window>
      <Window.DataContext>
        <DataModel />
      </Window.DataContext>
    
      <CartesianChart Height="500"
                      Series="{Binding SeriesCollection}">
        <CartesianChart.AxisX>
          <Axis Sections="{Binding SectionsCollection}"
                LabelFormatter="{Binding LabelFormatter}">
            <Axis.Separator>
              <Separator Step="10" />
            </Axis.Separator>
          </Axis>
        </CartesianChart.AxisX>
        <CartesianChart.AxisY>
          <Axis>
            <Axis.Separator>
              <Separator Step="5" />
            </Axis.Separator>
          </Axis>
        </CartesianChart.AxisY>
      </CartesianChart>
    </Window>