Search code examples
c#wpfxamldata-bindinglivecharts

Setting the colour of a LiveCharts Series that has custom labels using XAML Binding


The typical way of setting the Series Fill and Stroke are explained perfectly on the Livecharts website. However, in order to set custom labels for points you need to create the Series in the view model (Shown below). This prevents you from being able to call Fill or Stroke in the XAML as you don't have each series being created like the example below.

<lvc:CartesianChart Name="Chart" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="15">
   <lvc:CartesianChart.Series>
      <lvc:LineSeries Values="{Binding Values}" LineSmoothness="1" StrokeThickness="10" 
                      DataLabels="True" FontSize="20" Foreground="#6B303030"
                      Stroke="White" Fill="Transparent" PointGeometrySize="0"/>
   </lvc:CartesianChart.Series>

My current code which creates the series and its associated labels.

ViewModel

ABValuesSC = new SeriesCollection
    {
        new LineSeries
        { Values = ABValues,
            DataLabels = true,
            FontSize = 14,
            //MinPointShapeDiameter = 15,
            StrokeDashArray = new System.Windows.Media.DoubleCollection {2},
            Fill = System.Windows.Media.Brushes.Transparent,
            LabelPoint = point =>
            {if(point.Key==0)
                {
                    return "A";
                }
            else
                {
                    return "B";
                }
            }
        },
        new ScatterSeries
        { Values = TriggerValues,
            DataLabels = true,
            FontSize = 14,
            MinPointShapeDiameter = 15,
            LabelPoint = point =>
            {if(point.Key==0)
                {
                    return "1";
                }
            else
                {
                    return "2";
                }
            }
        },
        new LineSeries
        { Values = NAVmatValues,
            LineSmoothness=0,
        }
    };

XAML

<lvc:CartesianChart  Series="{Binding ABValuesSC}"/> 

Giving you this output.

enter image description here

Is there a method for accessing a series fill for the chart to change it from the default and have it be bindable? for example would it be possible to have the colours be bound to a list or is there a better way of making the labels for my chart such that i can use a similar method to the example at the top of this post?


Solution

  • Instead of creating a SeriesCollection programmatically and bind it to the View, its possible to define (most) of these Things directly in the XAML and only bind the Things you need to change in your ViewModel.

    Move to XAML

    As far as I understood your code, you only want to change the Values and the Fill in your ViewModel, so we put your "configuration" in the XAML which looks something like this:

    <lvc:CartesianChart>
       <lvc:CartesianChart.Series>
          <lvc:LineSeries Values="{Binding ABValues}" DataLabels="True" FontSize="14" StrokeDashArray="1,1" Fill="{Binding ABColor}" LabelPoint="{Binding ABLabelPoint}"/>
          <lvc:ScatterSeries Values="{Binding TriggerValues}" DataLabels="True" FontSize="14" MinPointShapeDiameter="15" LabelPoint="{Binding TriggerLabelPoint}"/>
          <lvc:LineSeries Values="{Binding NAVmatValues}" LineSmoothness="0"/>
       </lvc:CartesianChart.Series>         
    </lvc:CartesianChart>
    

    LabelPoint Binding

    The LabelPoint cant be set (or at least i dont know how) in the XAML and must be provided as a Property in your ViewModel (see Code below)

    class YourClass
    {
        //Property to Bind
        public Func<ChartPoint,string> ABLabelPoint { get; set; }
    
        //Constructor
        public YourClass()
        {
            //Define LabelPoint, where 0 = A, 1 = B etc.
            //Or use your Code, doesent really matter
            ABLabelPoint = point => ((char)(point.X + 65)).ToString();
        }
    }
    

    (Dont forget to do this for the Scatterseries LabelPoint as TribberLabelPoint Property)

    Values Binding

    The Values are now bound, therefore you must expose them as a Property like this

    public ChartValues<ValueType> ABValues { get; set; }
    

    Note: Replace ValueType with the used Type, eg. int or byte.

    Fill Color Binding

    Like the Values, the Fill color is bound to a Property which must be implemented. Make sure you notify the View when the Color Changes (see INotifyPropertyChanged)

    If your class already has this interface implemented it could look like this

    //private Field
    private SolidColorBrush _abColor = new SolidColorBrush(Colors.Green);
    
    //Public Property which the XAML binds to
    public SolidColorBrush ABColor
    {
        get { return _abColor; }
        set
        {
            _abColor = value;
            OnPropertyChanged();
        }
    }