Pre loader

Axis.GetDataValue returns unexpected (incorrect?) value when a Chart Title or Legend is present

Welcome to the SciChart Forums!

  • Please read our Question Asking Guidelines for how to format a good question
  • Some reputation is required to post answers. Get up-voted to avoid the spam filter!
  • We welcome community answers and upvotes. Every Q&A improves SciChart for everyone

WPF Forums | JavaScript Forums | Android Forums | iOS Forums

Answered
0
0

I’m in the process of evaluating SCIChart for purchase and have encountered what appears to be a bug in the Axis.GetDataValue method when a Title or Legend is present on the chart.

I am placing an annotation on the chart surface at the exact point a right mouse click raises a context menu. The annotation position is set as follows:

var newLabel = (LabelViewModel) e.NewItems[0];
newLabel.X1 = (DateTime) XAxis.GetDataValue(LastRightClickPoint.X);
newLabel.Y1 = (double) YAxis.GetDataValue(LastRightClickPoint.Y);
AddAnnotations(newLabel);

When there is no title, or legend on the chart surface this works exactly as expected and the annotation is placed exactly where the mouse click occurred.

When a title or legend is present on the surface, the annotation placement is shifted exactly the height of the title + the height of legend down from the spot of the mouse click coordinates.

Is this behavior expected? Is there something I’m not taking into account? Is there any easy way to get the pixel offset created by the title or legend?

I obtain the mouse cursor position by overiding the OnModifierMouseDown in a CustomAnnotation chart modifier class:

  /// <summary>
/// The CustomAnnotationChartModifiers provides a bridge between ViewModel and SciChartSurface, where we can 
/// access the Labels (via data binding) as well as the SciChart API to add, remove and manipulate annotations
/// </summary>
public class CustomAnnotationChartModifier : ChartModifierBase
{

    public Point LastRightClickPoint { get; set; }

    public static readonly DependencyProperty LabelsSourceProperty =
        DependencyProperty.Register(
            "LabelsSource",
            typeof (ObservableCollection<LabelViewModel>),
            typeof (CustomAnnotationChartModifier),
            new PropertyMetadata(OnLabelsSourceChanged));


    // Here LabelsSource is IEnumerable, but you could easily make it ObservableCollection<LabelViewModel> 
    // in order to get changed notifications when items are added to, or removed from the collection
    public ObservableCollection<LabelViewModel> LabelsSource
    {
        get
        {
            var labels =  (ObservableCollection<LabelViewModel>)GetValue(LabelsSourceProperty);
            return labels;
    }
        set { SetValue(LabelsSourceProperty, value); }
    }

    // Get a notification when new labels are set.
    private static void OnLabelsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var modifier = (CustomAnnotationChartModifier) d;
        var oldLabels = e.OldValue as INotifyCollectionChanged;
        var newLabels = e.NewValue as INotifyCollectionChanged;


        IEnumerable newValue = e.NewValue as IEnumerable;
        if (newValue != null)
        {
            if (oldLabels != null)
            {
                oldLabels.CollectionChanged -= modifier.OnLabelsCollectionChanged;
            }
            if (newLabels != null)
            {
                newLabels.CollectionChanged += modifier.OnLabelsCollectionChanged;
            }
            modifier.RebuildAnnotations();
        }

    }

    private  void OnLabelsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {

        if (e.NewItems  != null)
        {
            var newLabel = (LabelViewModel) e.NewItems[0];
            newLabel.X1 = (DateTime) XAxis.GetDataValue(LastRightClickPoint.X);
            newLabel.Y1 = (double) YAxis.GetDataValue(LastRightClickPoint.Y);
            AddAnnotations(newLabel);
        }

        if (e.OldItems != null)
        {
           RemoveAnnotations(e.OldItems);
        }
    }


    private void RemoveAnnotations(IList annotationViewModels)
    {
        if (base.ParentSurface != null)
        {
            foreach (var annotationViewModel in annotationViewModels)
            {
                var annotation = base.ParentSurface.Annotations.FirstOrDefault(a => a.DataContext == (annotationViewModel as LabelViewModel)) ;
                base.ParentSurface.Annotations.Remove(annotation);
            }
        }
    }

    private void AddAnnotations(LabelViewModel annotationViewModel)
    {
        if (base.ParentSurface != null)
        {
            base.ParentSurface.Annotations.Add( new CustomTextAnnotation() {DataContext = annotationViewModel});
        }
    }


    // Recreate all annotations
    private void RebuildAnnotations()
    {
        if (base.ParentSurface != null && LabelsSource != null)
        {
            // Take a look at the base class, ChartModifierBase for a wealth of API 
            // methods and properties to manipulate the SciChartSurface
            var annotationCollection = base.ParentSurface.Annotations;
            annotationCollection.Clear();

            foreach (var item in LabelsSource)
            {
                annotationCollection.Add(new CustomTextAnnotation() { DataContext = item });
            }
        }
    }

    /// <summary>
    /// Called when the Chart Modifier is attached to the Chart Surface
    /// </summary>
    public override void OnAttached()
    {
        base.OnAttached();

        // Catch the condition where LabelsSource binds before chart is shown. Rebuild annotations
        if (LabelsSource != null && base.ParentSurface.Annotations.Count == 0)
        {
            RebuildAnnotations();
        }

        //var mainWindow = FindLogicalParent<Window>();

        //mainWindow.PreviewKeyDown -= Annotation_PreviewKeyDown;
    }


    public override void OnModifierMouseDown(ModifierMouseArgs e)
    {
        base.OnModifierMouseDown(e);
        if (e.MouseButtons == MouseButtons.Right)
        {
            //  AddAnnotation(e.MousePoint);
            LastRightClickPoint = e.MousePoint;
        }
    }
  • You must to post comments
Best Answer
0
0

I am considering applying server-side licensing for my javerScript application.

In the document below, there is a phrase “Our server-side licensing component is written in C++.”
(https://support-dev.scichart.com/index.php?/Knowledgebase/Article/View/17256/42/)

However, there is only asp.net sample code on the provided github.
(https://github.com/ABTSoftware/SciChart.JS.Examples/tree/master/Sandbox/demo-dotnet-server-licensing)

I wonder if there is a sample code implemented in C++ for server-side licensing.

Can you provide c++ sample code?
Also, are there any examples to run on Ubuntu?

  • Tell O'Neal
    Yes this was exactly the issue. Thanks for the quick response.
  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.

Try SciChart Today

Start a trial and discover why we are the choice
of demanding developers worldwide

Start TrialCase Studies