If you recall we instantiated a collection of LabelViewModels in the MainViewModel. We need to bind to these and add them to the chart. To do this we can create a custom ChartModifier.<\/p>\n
SciChart exposes a rich API for interacting with the chart data or visible ranges. By inheriting from ChartModifierBase, you can access API functions for manipulating range, responding to mouse events etc\u2026<\/p>\n
Let\u2019s get started. Create a class which inherits ChartModifierBase. We are going to add a DependnecyProperty called LabelsSource, of type IEnumerable. We will later bind this directly to the MainViewModel.Labels property<\/p>\n
public class CustomAnnotationChartModifier : ChartModifierBase\r\n{\r\n public static readonly DependencyProperty LabelsSourceProperty = DependencyProperty.Register(\"LabelsSource\", typeof(IEnumerable), typeof(CustomAnnotationChartModifier), new PropertyMetadata(null, OnLabelsSourceChanged));\r\n\r\n \/\/ Here LabelsSource is IEnumerable, but you could easily make it \r\n \/\/ ObservableCollection<LabelViewModel> \r\n \/\/ in order to get changed notifications when items are added to, or removed from the collection\r\n public IEnumerable LabelsSource\r\n {\r\n get { return (IEnumerable) GetValue(LabelsSourceProperty); }\r\n set { SetValue(LabelsSourceProperty, value); }\r\n }\r\n\r\n \/\/ Get a notification when new labels are set.\r\n private static void OnLabelsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n {\r\n var modifier = (CustomAnnotationChartModifier) d;\r\n IEnumerable newValue = e.NewValue as IEnumerable;\r\n if (newValue == null) return;\r\n\r\n modifier.RebuildAnnotations();\r\n }\r\n\r\n \/\/ Recreate all annotations\r\n private void RebuildAnnotations()\r\n {\r\n \/\/ Todo\r\n }\r\n\r\n \/\/\/ <summary>\r\n \/\/\/ Called when the Chart Modifier is attached to the Chart Surface\r\n \/\/\/ <\/summary>\r\n public override void OnAttached()\r\n {\r\n base.OnAttached();\r\n\r\n \/\/ Catch the condition where LabelsSource binds before chart is shown. Rebuild annotations\r\n if (LabelsSource != null && base.ParentSurface.Annotations.Count == 0)\r\n { \r\n RebuildAnnotations();\r\n }\r\n }\r\n}<\/pre>\n <\/p>\n
Ok so far, this is really simple. Now you can add the CustomAnnotationChartModifier to the ScIChartSurface. You can also use this alongside other chart modifiers, e.g. ZoomPanModifier, RubberBandXyZoomModifier, ZoomExtentsModifier if placed in a modifier group. We\u2019re going to start off by just adding the single modifier and declaring the binding to LabelsSource property in the MainViewModel:<\/p>\n
<\/p>\n
<s:SciChartSurface SeriesSource=\"{Binding ChartSeries}\" \r\n\r\n<!-- Omitted for brevity ... -->\r\n\r\n<s:SciChartSurface.ChartModifier>\r\n <local:CustomAnnotationChartModifier LabelsSource=\"{Binding ChartLabels}\"\/>\r\n<\/s:SciChartSurface.ChartModifier>\r\n\r\n<\/s:SciChartSurface><\/pre>\n <\/p>\n
If you run the app now, you should be able to put a breakpoint in the CustomAnnotationChartModifier.OnLabelsSourceChanged method and step through to see if the binding is wired up correctly.<\/p>\n
What next? Lets add and position our annotations. Remember the RebuildAnnotations() method with its \/\/TODO comment? Ok, now lets add this body to the chart.<\/p>\n
<\/p>\n
\/\/ Recreate all annotations, called when LabelsSource property changes\r\n\/\/ or when the CustomAnnotationChartModifier is attached to the parent surface\r\nprivate void RebuildAnnotations()\r\n{\r\n if (base.ParentSurface == null || LabelsSource == null)\r\n return;\r\n\r\n \/\/ Take a look at the base class, ChartModifierBase for a wealth of API \r\n \/\/ methods and properties to manipulate the SciChartSurface\r\n var annotationCollection = base.ParentSurface.Annotations;\r\n annotationCollection.Clear();\r\n\r\n foreach(var item in LabelsSource)\r\n {\r\n annotationCollection.Add(new CustomTextAnnotation() { DataContext = item });\r\n }\r\n}<\/pre>\n <\/p>\n
We also need a custom annotation. All this is, is a class that inherits CustomTextAnnotation but has the bindings to LabelText and LabelTooltip. There are other ways to do this, for instance:<\/p>\n