How to Dynamically Handle Multiple Series in a ChartSeriesCollection Using MVVM in WPF SfChart
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:
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!