SciChart WPF 2D Charts > Tutorials > MVVM > Tutorial 07b - Adding Annotations with MVVM
Tutorial 07b - Adding Annotations with MVVM

Adding Annotations in MVVM

Source code for this tutorial can be found at our SciChart.WPF.Examples Github Repository under Tutorials section.

We want to now add some Annotations in MVVM. To do this, lets create first our Annotation type, taken from Tutorial 07 - Adding Annotations.

Copy Code
<s:CustomAnnotationForMvvm x:Class="SciChart.Mvvm.Tutorial.InfoAnnotation"
        <LinearGradientBrush x:Key="infoAnnotationBackground" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0.5" Color="#FFF" />
            <GradientStop Offset="1" Color="#77C0D4EE" />
        <!-- Low-cost drop shadow -->
        <Border CornerRadius="2" BorderThickness="1" BorderBrush="#333" Background="#333" Opacity="0.8" Margin="2,2,0,0"/>
        <!-- News bullet body -->
        <Border CornerRadius="2" BorderThickness="1" BorderBrush="#555" Background="{StaticResource infoAnnotationBackground}">
            <TextBlock Text="N" Padding="3" FontWeight="Bold" FontSize="10"/>
        <!-- Creating the tooltip. In the TradeOverlayExampleViewModel we set a News
        object as datacontext of this annotation -->
            <ToolTip Foreground="#222">
                <Grid Margin="6" MaxHeight="100" MaxWidth="150">
                    <TextBlock Text="Show more info here!" Foreground="#3333FF"/>
Copy Code
using SciChart.Charting.Visuals.Annotations;
namespace SciChart.Mvvm.Tutorial
    public partial class InfoAnnotation : CustomAnnotationForMvvm
        public InfoAnnotation()

We also need a ViewModel for the custom annotation. We base this off CustomAnnotationViewModel as follows:

Copy Code
using System;
using SciChart.Charting.Model.ChartSeries;
namespace SciChart.Mvvm.Tutorial
    public class InfoAnnotationViewModel : CustomAnnotationViewModel
        public override Type ViewType
            get { return typeof(InfoAnnotation); }

Now to add these to our charts using MVVM. We can't access the SciChartSurface.Annotations property, as this is on the SciChartSurface which is a view item, and cannot (should not) be accessed from the ViewModel.

Instead we're going to use the AnnotationsBinding MarkupExtension to add these to the chart.


Dynamically Adding Annotations in the ViewModel

In order to add Annotations in the ViewModel, we need to do a few things:

  1. Declare a collection of IAnnotationViewModel, similar to the RenderableSeries collection.
  2. Add our InfoAnnotationViewModel to this collection with X1,Y1 values to tag them onto the chart.
  3. In the view, we need to include a default style for InfoAnnotation to inherit from one of our built-in styles. This ensures that X1,X2 and other default properties are bound.

Let's do this below:

Copy Code
    public class MainViewModel : BindableObject
        private string _chartTitle = "Hello SciChart World!";
        private string _xAxisTitle = "XAxis";
        private string _yAxisTitle = "YAxis";
        private bool _enablePan;
        private bool _enableZoom = true;
        private XyDataSeries<double, double> _lineData;
        private readonly DummyDataProvider _dummyDataProvider = new DummyDataProvider();
        private AutoRangeViewportManager _viewportManager = new AutoRangeViewportManager();
        private ObservableCollection<IAnnotationViewModel> _annotations = new ObservableCollection<IAnnotationViewModel>();
        private ObservableCollection<IRenderableSeriesViewModel> _renderableSeries = new ObservableCollection<IRenderableSeriesViewModel>();
        public MainViewModel()
            // Subscribe to future updates
            int i = 0;
            _dummyDataProvider.SubscribeUpdates(newValues =>
                // Append when new values arrive
                _lineData.Append(newValues.XValues, newValues.YValues);
                // Every 100th data point, add an annotation
                if (i % 100 == 0)
                    Annotations.Add(new InfoAnnotationViewModel
                        X1 = _lineData.XValues.Last(),
                        Y1 = 0.0,
                        // Specify that the point (X1, Y1) is located at the bottom-center of the annotation
        private void CreateChartData()
            var initialDataValues = _dummyDataProvider.GetHistoricalData();
            // Create a DataSeries. We later apply this to a RenderableSeries
            _lineData = new XyDataSeries<double, double> { SeriesName = "TestingSeries" };
            // Append some data to the chart                                 
            _lineData.Append(initialDataValues.XValues, initialDataValues.YValues);         
        private void CreateChartSeries()
            // Create a RenderableSeries. Apply the DataSeries created before 
            _renderableSeries = new ObservableCollection<IRenderableSeriesViewModel>();
            RenderableSeries.Add(new LineRenderableSeriesViewModel
                StrokeThickness = 2,
                Stroke = Colors.SteelBlue,
                DataSeries = _lineData,
                StyleKey = "LineSeriesStyle"
        public ObservableCollection<IAnnotationViewModel> Annotations
            get { return _annotations; }
                _annotations = value;
        public ObservableCollection<IRenderableSeriesViewModel> RenderableSeries
            get { return _renderableSeries; }
                _renderableSeries = value;
        public AutoRangeViewportManager ViewportManager
            get { return _viewportManager; }
                _viewportManager = value;
        // ... ChartTitle, XAxisTitle, YAxisTitle, EnableZoom, EnablePan omitted for brevity ...


We need to update our view code as well.

  1. Ensure that all the resources in MainWindow.xaml are included in a resource dictionary.
  2. Include the default.xaml styles from SciChart. We need this for our base styule for CustomAnnotation
  3. Include a style for InfoAnnotation. We need this to ensure default properties such as X1,Y1 are data-bound.
Copy Code
            <local:MainViewModel x:Key="MainViewModel"/>
            <!-- The TooltipControl template is defined below -->
            <!-- Change this if you want to have a non-default tooltip container -->
            <!-- The ContentPresenter is bound to the DataContext (a SeriesInfo type) -->
            <!-- and the ContentTemplate is the DataTemplate for the SeriesInfo -->
            <!-- Finally, the TooltipContainerStyle is set on the RenderableSeries via Style -->
            <Style x:Key="TooltipContainer" TargetType="s:TooltipControl">
                <Setter Property="Template">
                        <ControlTemplate TargetType="s:TooltipControl">
                            <Border Background="#FF6495ED"
                                <ContentPresenter Content="{TemplateBinding DataContext}"
                                                  ContentTemplate="{TemplateBinding ContentTemplate}"/>
            <!-- Tooltip Template for an XyDataSeries binds to XySeriesInfo -->
            <!-- Check out the properties on XySeriesInfo to see what you can bind to -->
            <DataTemplate x:Key="TooltipTemplate" DataType="s:XySeriesInfo">
                <StackPanel Orientation="Vertical">
                    <TextBlock Foreground="White" Text="{Binding SeriesName, Mode=OneWay, StringFormat='Series: {0}'}"/>
                    <TextBlock Foreground="White" Text="{Binding FormattedXValue, Mode=OneWay, StringFormat='X-Value: {0}'}"/>
                    <TextBlock Foreground="White" Text="{Binding FormattedYValue, Mode=OneWay, StringFormat='Y-Value: {0}'}"/>
            <!-- Style applied via x:Key name in ViewModel. See StyleKey property of LineRenderableSeriesViewModel -->
            <Style x:Key="LineSeriesStyle" TargetType="s:BaseRenderableSeries">
                <Setter Property="s:RolloverModifier.TooltipContainerStyle" Value="{StaticResource TooltipContainer}"/>
                <Setter Property="s:RolloverModifier.TooltipTemplate" Value="{StaticResource TooltipTemplate}"/>
                <Setter Property="s:RolloverModifier.IncludeSeries" Value="True"/>
                <Setter Property="StrokeThickness" Value="2"/>

Running the code, we now see this: