Pre loader

AnnotationLabel causes RotationAngle BindingException

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

0
0

We have a SciChartSurface that displays data, and includes a collection of threshold lines that can be modified by the user by dragging.
To accomplish this, we are using a class that inherits from ChartModifierBase that includes an attached property for binding an IEnumerable:

public static readonly DependencyProperty ThresholdsSourceProperty =
    DependencyProperty.Register
    (
        "ThresholdsSource",
        typeof(IEnumerable),
        typeof(CustomThresholdModifier),
        new PropertyMetadata(null, OnThresholdsSourceChanged)
     );

public IEnumerable ThresholdsSource
{
    get { return (IEnumerable)GetValue(ThresholdsSourceProperty); }
    set { SetValue(ThresholdsSourceProperty, value); }
}

The property includes a callback method (OnThresholdsSourceChanged) which is used to populate the Annotations collection of the parent SciChartSurface:

private static void OnThresholdsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var thresholdAnnotationModifier = d as CustomThresholdModifier;
    if (thresholdAnnotationModifier != null)
    {
        var newValue = e.NewValue as IEnumerable;
        if (newValue == null) return;

        thresholdAnnotationModifier.RebuildAnnotations();
    }
}

private void RebuildAnnotations()
{
    if ((ParentSurface == null) || (ThresholdsSource == null)) return;

    var annotationCollection = ParentSurface.Annotations;
    annotationCollection.Clear();

    foreach (IThresholdViewModel item in ThresholdsSource)
    {
        var threshold = new CustomHorizontalLineAnnotation{ DataContext = item };
        annotationCollection.Add(threshold);
    }
}

When this code is run, a binding exception occurs, but not until all of the code is successful. The exception:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement
or FrameworkContentElement for target element.
BindingExpression:Path=RotationAngle; DataItem=null; target element is
‘RotateTransform’ (HashCode=28139356); target property is ‘Angle’
(type ‘Double’)

The exception is clearly thrown downstream by some WPF thread, or I’d be able to wrap a try/catch around this and have better details.

If I comment out the line that creates the CustomHorizontalLineAnnotation, no exception.
If I add a short artificial delay before the first creation of CustomHorizontalLineAnnotation, no exception.
If I set “ShowLabel” = False in the HorizontalLineAnnotation, no exception.
If I add a dummy creation of CustomHorizontalLineAnnotation in the constructor of my CustomThresholdModifier, no exception.
If I add a dummy creation of AnnotationLabel in the constructor of my CustomThresholdModifier, no exception.

In short, the root cause of the binding exception seems to be coming from the creation of an AnnotationLabel in HorizontalLineAnnotation, either through setting ShowLabel=True, or adding it to the AnnotationLabels collection of the HorizontalLineAnnotation.

Any thoughts? I’d like to use the dummy creation of AnnotationLabel in the constructor as the solution to the problem, but this feels too much like a hack, and likely wont pass muster for my team. Maybe there’s some “best practice” being violated here, in using the modifier to update the annotation on property change?

Thanks!

Version
4.2.3 10185
  • You must to post comments
0
0

Hi Robin,

A lot of ifs / and buts in this code. The HorizontalLineAnnotation you are using is a custom one (not a scichart one). you have an older version of scichart, you’re using a non-standard way of building annotations (v5 now advocates using AnnotationsBinding and ViewModels in code).

So I’m not sure what to suggest really? Perhaps go about it from a different angle? Strip the application down to component parts and isolate things one at a time until you find a probable cause.

  • You must to post comments
0
0

Hi Andrew,

I know it’s related to the AnnotationLabel, but I don’t think it’s AnnotationLabel’s “fault”, per se. I’ve used SciChart for many years and have mostly been able to overcome obstacles, but this one baffles me. I’m thinking I might shelf this problem for now, and see about refactoring the logic someday, as you suggested, when we upgrade our build to a newer version of SciChart.

As always, thanks for the quick response!

  • You must to post comments
0
0

I was revisiting this recently, because we finally upgraded our project to use SciChart v5. I experimented a bit with the AnnotationsBinding, but ran into the same problem. Getting rid of all the bits and pieces, I have isolated it down to a single simple problem. Create a window with a SciChartSurface, and simply add a single HorizontalLineAnnotation when the window is loaded:

using System.Windows;
using System.Windows.Media;
using SciChart.Charting.Visuals.Annotations;

namespace SciChartBindingError
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Loaded += OnLoaded;
        }
        private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            LoadAnnotation();
        }

        void LoadAnnotation()
        {
            var line = new HorizontalLineAnnotation
            {
                FontSize = 11,
                Foreground = Brushes.White,
                IsEditable = true,
                LabelPlacement = LabelPlacement.Axis,
                ShowLabel = true,
                Stroke = Brushes.Red,
                StrokeThickness = 2,
                LabelTextFormatting = "0",
                Y1 = 0,
            };
            sciChartSurface.Annotations.Add(line);
        }
    }
}

If you look at the console output, you’ll see the error:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement
or FrameworkContentElement for target element.
BindingExpression:Path=RotationAngle; DataItem=null; target element is
‘RotateTransform’ (HashCode=21574462); target property is ‘Angle’
(type ‘Double’)

It only happens the FIRST time a HorizontalLineAnnotation is created, and then only if ShowLabel=true. Once the error is encountered, the horizontal line appears with no further problems, and all future HorizontalLineAnnotations are error-free.

Why then do I worry about it? Primarily because in development, we use a library called “WpfBindingErrors” (https://github.com/bblanchon/WpfBindingErrors) to turn all binding errors into exceptions. The idea is to catch binding errors early, and the group I’m working in, found this to be a useful tool. That said, it’s not so useful anymore when the binding exception is thrown on every launch.

Seems like an issue with AnnotationLabel, because of the fact there are no problems if ShowLabel=false, but I’m not sure. Manually adding an annotation label with ShowLabel=false, also creates the same binding exception. Also tried setting RotationAngle=0 on the manually added annotation label, with no success.

Anyway, that’s the root of it.

Thanks,
Robin

  • Andrew Burnett-Thompson
    Hi Robin, we consider issues like this (where the chart works but there is an early binding error once per chart load) to be quite low priority: we can’t fix all of WPF’s weirdness … :) That being said, the latest v5.1.1 nightly build has a fix in it related to MVVM API where some users reported that some bindings were not working. The reason: The Templates were initialised after DataContext was applied (WPF Wierdness). This is resolved and it may help your problem too. If not, I’m afraid – as I said we consider working chart but with one small anomaly low priority. Best regards, Andrew
  • Robin Warren
    Understood, and I agree with you about WPF weirdness being a lower priority. I’ll check out v5.1.1 and see if that helps. Thanks as always for your input!
  • Robin Warren
    I meant to add: there is an easy workaround. In our App.xaml.cs constructor, we simply new up a dummy AnnotationLabel, that we ignore and let go out of scope. That seems to consume the first binding error without reporting it, and allows the chart to function normally after that. :-)
  • You must to post comments
Showing 3 results
Your Answer

Please first to submit.