Articles in this section
Category / Section

How to Dynamically Handle Multiple Series in a ChartSeriesCollection Using MVVM in WPF SfChart

10 mins read

This article explains how to dynamically manage multiple chart series in a Syncfusion WPF SfChart control using the Model-View-ViewModel (MVVM) pattern. By binding the Series property to a ChartSeriesCollection in a ViewModel, you can programmatically add, remove, or modify series at runtime in response to user actions or other application logic. This approach is ideal for scenarios requiring interactive or data-driven chart UIs.

Follow these steps to implement MVVM data binding for WPF Chart series:

Step 1: Create a DataModel to represent the points in your chart series. This model should contain properties for your X and Y values.

C#

 public class Model
 {
     public string XValue { get; set; }

     public double YValue { get; set; }

     public Model(string xValue, double yValue)
     {
         XValue = xValue;
         YValue = yValue;
     }
 }

Step 2: Define your ViewModel to hold data and manage chart series. The ViewModel will store the data as observable collections of Model objects, along with the ChartSeriesCollection to which the SfChart will bind, adhering to the MVVM pattern.

C#

public class ViewModel : INotifyPropertyChanged
{
    private ChartSeriesCollection? series;

    private List<SplineSeries> allSplineSeries;

    public ChartSeriesCollection? Series
    {
        get => series;
        set
        {
            series = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Series)));
        }
    }

    public ObservableCollection<Model> DataSource1 { get; set; }
    public ObservableCollection<Model> DataSource2 { get; set; }
    public ObservableCollection<Model> DataSource3 { get; set; }
    public ObservableCollection<Model> DataSource4 { get; set; }
    public SplineSeries? SplineSeries1 { get; set; }
    public SplineSeries? SplineSeries2 { get; set; }
    public SplineSeries? SplineSeries3 { get; set; }
    public SplineSeries? SplineSeries4 { get; set; }

    public ViewModel()
    {
        DataSource1 = new ObservableCollection<Model>
        {
            new Model("Benz", 2),
            new Model("Volvo", 35),
            new Model("Jaguar", 30),
            new Model("BMW", 15),
            new Model("Toyota",10),
            new Model("Audi", 5)
        };

        DataSource2 = new ObservableCollection<Model>
        {
            new Model("Benz", 12),
            new Model("Volvo", 30),
            new Model("Jaguar", 28),
            new Model("BMW", 35),
            new Model("Toyota", 15),
            new Model("Audi", 10)
        };

        DataSource3 = new ObservableCollection<Model>
        {
            new Model("Benz", 25),
            new Model("Volvo", 10),
            new Model("Jaguar", 20),
            new Model("BMW", 10),
            new Model("Toyota", 35),
            new Model("Audi", 30)
        };

        DataSource4 = new ObservableCollection<Model>
        {
            new Model("Benz", 35),
            new Model("Volvo",44),
            new Model("Jaguar", 40),
            new Model("BMW", 44),
            new Model("Toyota", 30),
            new Model("Audi", 40)
        };

        SplineSeries1 = new SplineSeries
        {
            ItemsSource = DataSource1,
            XBindingPath = "XValue",
            YBindingPath = "YValue",
            LegendIcon= ChartLegendIcon.Circle,
            Label = "Q1"
        };

        SplineSeries2 = new SplineSeries
        {
            ItemsSource = DataSource2,
            XBindingPath = "XValue",
            YBindingPath = "YValue",
            LegendIcon = ChartLegendIcon.Circle,
            Label = "Q2"

        };

        SplineSeries3 = new SplineSeries
        {
            ItemsSource = DataSource3,
            XBindingPath = "XValue",
            YBindingPath = "YValue",
            LegendIcon = ChartLegendIcon.Circle,
            Label = "Q3"
        };

        SplineSeries4 = new SplineSeries
        {
            ItemsSource = DataSource4,
            XBindingPath = "XValue",
            YBindingPath = "YValue",
            LegendIcon = ChartLegendIcon.Circle,
            Label = "Q4"
        };
        
        Series = new ChartSeriesCollection()
        {
            SplineSeries1,
            SplineSeries2,
        };

        allSplineSeries = new List<SplineSeries>
        {
            SplineSeries1,
            SplineSeries2,
            SplineSeries3,
            SplineSeries4
        };
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    public void AddSeries()
    {
        foreach (var spline in allSplineSeries)
        {
            if (!Series!.Any(s => s.Label == spline.Label))
            {
                Series?.Add(spline);
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Series)));
                break;
            }
        }
    }

    public void RemoveSeries()
    {
        if (Series != null && Series.Count > 1)
        {
            Series.RemoveAt(Series.Count - 1);
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Series)));
        }
    }
} 

Step 3: For Chart control initialization, you can refer this UG documentation. Then, bind the SfChart’s Series property to the Series property.

XAML

<chart:SfChart Series="{Binding Series}">

    <chart:SfChart.PrimaryAxis>
        <chart:CategoryAxis/>
    </chart:SfChart.PrimaryAxis>
    
    <chart:SfChart.SecondaryAxis>
        <chart:NumericalAxis/>
    </chart:SfChart.SecondaryAxis>
</chart:SfChart>

Step 4: We can add and remove series at runtime. There are two buttons on the UI that trigger the corresponding methods in the ViewModel. The Click events in the code-behind call the AddSeries() and RemoveSeries() methods, which are responsible for adding and removing series from the Series collection.

XAML

<Grid>
       <!-- ... Chart codes ... -->
       <Grid Grid.Row="2">
           <Grid.ColumnDefinitions>
               <ColumnDefinition Width="Auto"/>
               <ColumnDefinition Width="Auto"/>
           </Grid.ColumnDefinitions>
           <Button Content="Add Series" 
                   Padding="4"
                   Margin="4"
                   Click="Add_Button_Click" 
                   Height="45"
                   FontWeight="Bold"
                   Width="100"/>
           <Button Grid.Column="1" 
                   Click="Remove_Button_Click" 
                   Height="45"
                   Width="100"
                   Margin="4"
                   Padding="4"
                   FontWeight="Bold"
                   Content="Remove Series"/>
       </Grid>
   </Grid> 

C#

public partial class MainWindow : Window
 {
     public MainWindow()
     {
         InitializeComponent();
     }

     private void Add_Button_Click(object sender, RoutedEventArgs e)
     {
         if(viewModel != null)
         {
             viewModel.AddSeries();
         }
     }

     private void Remove_Button_Click(object sender, RoutedEventArgs e)
     {
         if (viewModel != null)
         {
             viewModel.RemoveSeries();
         }
     }
 } 

Output:

Output.gif

Download the complete sample from GitHub.

Conclusion:

I hope you enjoyed learning about how to dynamically handle multiple series in a ChartSeriesCollection using MVVM in WPF SfChart

You can refer to our WPF Chart feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications.

For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion®, you can try our 30-day free trial to check out our other controls.

If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied