Custom ChartModifiers - Part 4 - Custom Legend Data Sources

Created by Lex Smith, Modified on Fri, 29 Mar at 2:11 AM by Lex Smith

The ChartModifier API


If you haven't read it already, please see our article on Custom ChartModifier API Overview. In this article, we introduce the basics of the ChartModifier API including an overview of this powerful base class. 


The ChartModifier API is by far the most powerful API in the SciChart library. Using this API you can create behaviours which you can attach to a chart to perform custom Zooming, Panning, Annotation & Markers, Legend output and much much more. Any time you want to do something in C# code to alter the behaviour of a SciChartSurface you should be thinking about creating a custom modifier to do it.


Custom ChartModifiers Part 4 - Custom Legend Data Source


The fourth part in our series on Custom Chart Modifiers demonstrates how we create a Legend Data Source. In this example we're going to create something similar to what the SciChart LegendModifier does - expose a Collection of SeriesInfo that we can bind to in the view. You can easily take this custom modifier and extend it if you wanted to provide extra metadata to bind to in the legend. Watch the video below to see how we did this.



The SimpleLegendModifier Source


The entire SimpleLegendModifier class is included below. The code is fairly self-explanatory. Whenever the SciChartSurface renders, we perform a hit-test on all the RenderableSeries on the parent SciChartSurface using the right-most point on the Viewport. Then, we convert the HitTestInfo results into SeriesInfo - a flexible ViewModel containing information about the underlying Series. We can then bind to the SeriesInfo in the view, either by using a Legend control or even a simple ItemsControl.


using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using SciChart.Charting.ChartModifiers;
using SciChart.Charting.Model.ChartData;
using SciChart.Charting.Utility;
using SciChart.Charting.Visuals.RenderableSeries;
 
namespace TestSuite.ExampleSandbox.CustomModifiers
{
    public class SimpleLegendModifier : ChartModifierBase
    {
        /// 
        /// Defines the LegendData Dependency property
        /// 
        public static readonly DependencyProperty LegendDataProperty = DependencyProperty.Register("LegendData", typeof(ChartDataObject), typeof(SimpleLegendModifier));
 
        public SimpleLegendModifier()
        {
            this.SetCurrentValue(LegendDataProperty, new ChartDataObject { SeriesInfo = new ObservableCollection<SeriesInfo>() });
        }
 
        /// 
        /// Gets or sets the  which may be bound to
        /// 
        public ChartDataObject LegendData
        {
            get { return (ChartDataObject)GetValue(LegendDataProperty); }
            set { SetValue(LegendDataProperty, value); }
        }
 
        public override void OnParentSurfaceRendered(SciChartRenderedMessage e)
        {
            base.OnParentSurfaceRendered(e);
 
            // TODO here: Modify which RenderableSeries are passed in to GetSeriesInfo to alter output
            var seriesInfos = this.GetSeriesInfo(ParentSurface.RenderableSeries);
 
            // TODO here: if you experience flicker, it is a .NET4.5 bug. This occurs when updating an ObservableCollection
            // the solution believe it or not is to do a differential update, e.g. only change the SeriesInfo instance if a series was added or removed
            LegendData.SeriesInfo = new ObservableCollection<SeriesInfo>(seriesInfos);
        }
 
        private ObservableCollection<SeriesInfo> GetSeriesInfo(IEnumerable<IRenderableSeries> allSeries)
        {
            var seriesInfo = new ObservableCollection<SeriesInfo>();
 
            if (allSeries != null)
            {
                foreach (var renderableSeries in allSeries)
                {
                    if (renderableSeries == null || renderableSeries.DataSeries == null)
                    {
                        continue;
                    }
 
                    var hitResult = renderableSeries.DataSeries.HasValues
                                        ? renderableSeries.HitTest(new Point(ModifierSurface.ActualWidth, 0))
                                        : default(HitTestInfo);
 
                    var s = renderableSeries.GetSeriesInfo(hitResult);
 
                    seriesInfo.Add(s);
                }
            }
 
            return seriesInfo;
        }
    }
}


Get the Custom ChartModifier Sandbox application


The link to the complete application with all our custom chart modifiers can be found in Part 1.



Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article