SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, and now iOS Charting & Android Chart Components

Welcome to the SciChart Community Forums!

Please use the forums below to ask questions about SciChart. Take a moment to read our Question asking guidelines on how to ask a good question and our support policy

We also have a tag=SciChart on Stackoverflow.com where you can earn rep for your questions!

1
0

Hi,

I’m creating a CustomChartModifier which I am able to hook to a SciStockChart (a template item in a SciChartGroup MVVM) and now I’m having difficulties in adding the BoxAnnotation to the Chart.

This is the code I’m using in my ChartModifier and placing a breakpoint shows me that indeed the code runs through this method, however, I do not see any BoxAnnotation on my chart? I’ve even tried adding the Height and Width properties without any further success. Other CustomModifiers to draw Lines and Ellipses works without problems. Do BoxAnnotations work differently?

I’m looking to have the the user be able to draw a BoxAnnotation on the chart, free hand / dynamically.

SimpleBoxAnnotationModifier.cs

public override void OnModifierMouseDown(ModifierMouseArgs e)
{
        base.OnModifierMouseDown(e);

        var resources = new AnnotationStyles();
        // x:Key="BoxAnnotationStyle" TargetType="s:BoxAnnotation"
        var style = (Style)resources["BoxAnnotationStyle"];

        _annotationCreation = new AnnotationCreationModifier () { AnnotationType = typeof(BoxAnnotation), AnnotationStyle = style };

        this.ModifierSurface.Children.Add(_annotationCreation);
}

AnnotationStyles.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
                x:Class="ChartModifierBinding.AnnotationStyles">

<Style x:Key="BoxAnnotationStyle" TargetType="s:BoxAnnotation">
    <Setter Property="BorderBrush" Value="#279B27"/>
    <Setter Property="Background" Value="#551964FF"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="IsEditable" Value="True"/>
</Style>

Thanks for any pointers or tips!

  • You must to post comments
1
0

Hi Andrew,

Right now, using your AnnotationCreationModifier will do and what I’ve done was to extend AnnotationCreationModifier so that I could place some code in the default constructor

AnnotationCreationModifierEx

    public AnnotationCreationModifierEx()
    {
        var resources = new AnnotationStyles();
        // x:Key="BoxAnnotationStyle" TargetType="s:BoxAnnotation"
        var style = (Style)resources["BoxAnnotationStyle"];

        this.AnnotationStyle = style;
        this.AnnotationType = typeof(BoxAnnotation);            
    }

And in my XAML

<t:SciStockChartEx.ChartModifier>
    <s:ModifierGroup >
        <!-- Attach OnAnnotationCreated handler defined in code behind -->
        <s:AnnotationCreationModifier x:Name=&quot;annotationCreator&quot;>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="AnnotationCreated" SourceObject="{Binding RelativeSource={RelativeSource AncestorType={x:Type s:AnnotationCreationModifier}}}">
                    <i:InvokeCommandAction Command="{Binding OnAnnotationCreatedCommand}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </s:AnnotationCreationModifier>
    </s:ModifierGroup>
</t:SciStockChartEx.ChartModifier >

The only thing now is that how do I bind the AnnotationCreated to my ViewModel? I know it’s a UI interaction and supposedly it’s kinda ok to put it in the code behind, but I’ve been reading that it is bad practice for those MVVM purists.

I will need to handle this event because I would like to Reset the AnnotationCreationModifier because right now when drawing a BoxAnnotation, the mouse clicks goes weird and I would also like to be reported of the data coordinates. (I have read the API converting between pixels and data coordinates before however I’m not even at that point yet)

Option 2. If eventually I would like to handle the mouse events myself to allow for the dynamic placement of BoxAnnotations onto the SciStockChart (templated item inside a SciChartGroup) using the more standard Click and Drag, from my ChartModifier , mouse event down method, how do I start the creation of the BoxAnnotation? I know I have the X1 and Y1 values but is there a method/handler that I can call to have the BoxAnnotation creation started and placed onto my SciStockChart pane from the X1 and Y1 values I have from the ModifierMouseArgs in the OnModifierMouseDown function?

Likewise, OnModifierMouseUp, what is the method I must call on the BoxAnnotation object to close the BoxAnnotation???

BoxAnnotationChartModifier

    public override void OnModifierMouseDown(ModifierMouseArgs e)
    {
        base.OnModifierMouseDown(e);
        // Translates the mouse point to chart area, e.g. when you have left axis
        var pt = GetPointRelativeTo(e.MousePoint, this.ModifierSurface);

        var resources = new AnnotationStyles();
        // x:Key="BoxAnnotationStyle" TargetType="s:BoxAnnotation"
        var style = (Style)resources["BoxAnnotationStyle"];

        _annotationCreation = new AnnotationCreationModifier () { AnnotationType = typeof(BoxAnnotation), AnnotationStyle = style };
        _annotationCreation.Annotation.X1 = pt.X;
        _annotationCreation.Annotation.Y1 = pt.Y;

        this.ModifierSurface.Children.Add(_annotationCreation); ......

I feel this is wrong as I cannot see where it is starting the BoxAnnotation annotaton creation process?

I think I am missing something big in order to implement this option.

So, any hints on the binding issue for the first option so I can just get going for now and then revisit the CustomChartModifier where I handle the events later?

Thanks

  • Andrew
    Hi David, look up MVVM Event to command. There's a hundred different implementations out there, this is one http://social.technet.microsoft.com/wiki/contents/articles/18199.event-handling-in-an-mvvm-wpf-application.aspx
  • David T
    Andrew, thanks for the link, I've been looking at the MVVM Events to command, however from what I understand AnnotationCreated is not a standard MVVM Event command. From the link you sent me, I quote, "Only some controls can actually bind to a command through the Command property, notably those derived from System.Windows.Controls.Primitives.ButtonBase or System.Windows.Controls.MenuItem."From every example I've seen online, they always use the "Command" keyword in the xaml and even in the link you had posted. http://stackoverflow.com/questions/4897775/wpf-binding-ui-events-to-commands-in-viewmodel, http://stackoverflow.com/questions/7877532/wpf-event-binding-from-view-to-viewmodelAm I missing something major here??? Even using Expression Blend interaction triggers and the System.Windows.Interactivity.InvokeCommandAction class I'm not getting the result of just being able to bind the AnnotationCreated event to my ViewModel. ???
  • David T
    Andrew, could you comment on Option 2 also please? using a ChartModifier to allow a user to place BoxAnnotations by pointing and clicking on the chart? How does one hook that up? Examples?
  • Andrew
    Hi David, AnnotationCreated is an event, and event-to-command marshals any event, to an ICommand that you specify in your viewmodel. I suggest doing some reading around what Event-to-command is as it should be applicable to the above. Secondly, there's no examples for exactly what you want, sorry. We have examples that show you how to get mouse-down events on the chart (which you have), how to place annotations using data-coordinates (which you know) and how to convert mouse pixel coordinates to data coordinates (which is here http://support.scichart.com/index.php?/Knowledgebase/Article/View/17207/31/convert-pixel-to-data-coordinates). That's all you need to do really, mousedown -> Convert e.MousePoint to data coords -> Place annotation. I'd love to help further but I suggest you do some reading around these topics and then if you have specific single questions ask them. That way the forums are not cluttered and serve as a good reference to other users. Best regards, Andrew
  • You must to post comments
0
0

Hi Andrew,

I had a little help from Yuriy Z previously, months ago but I couldn’t get past the WPF namespace and binding tech part, but I’ve since taken a little crash course on it and then re-read what Yuiry Z had written, he proposed that I use Dependency Injection to add the modifiers to SciStockChart by extension, e.g. SciStockChartExtended and it works like a charm 😀 I am able to declare the SimpleRolloverModifier and others etc… in XAML to my SciStockChartExtended and all is well 😀

I’ve tried to declare X1Y1 etc… however without success, code snippet below

        // Translates the mouse point to chart area, e.g. when you have left axis
        var pt = GetPointRelativeTo(e.MousePoint, this.ModifierSurface);
        ...
        _annotationCreation.Annotation.X1 = pt.X;
        _annotationCreation.Annotation.Y1 = pt.Y;

I have also tried to declare that in the the XAML of the BoxAnnotation style using the Setter Properties and Values, still without success.

I’m not too familiar on the differences of this.ModifierSurface.Children and this.ParentSurface.Annotations yet as I was following the SimpleRolloverModifier example which uses that line to add a vertical line to the mouse position, I paste a snippet from line 69 and 70 of that file in your example.

        // Add the rollover line to the ModifierSurface, which is just a canvas over the main chart area, on top of series
        this.ModifierSurface.Children.Add(_line);

So now my question is, is it even possible what I am trying to achieve? Just to allow the user to be able to dynamically draw a box on a SciStockChart templated item inside a SciChartGroup? Am I going about it the right way with a CustomModifier? Or do I need something else?

I can’t seem to find much information or examples regarding to event handlers of capturing the left click and somehow attaching that to a BoxAnnotation start creation etc…???

I’m just very confused at the moment, could you please clarify with some links or offer a code snippet to the solution to help me? 😀

Thank you

  • You must to post comments
0
0

Hi David,

The CustomModifier approach, everything, is great. The place where you are going wrong is you are mixing and matching two different APIs for drawing over the chart.

Please see this forum post for more details about the difference between the Annotations API and ModifierSurface: https://www.scichart.com/questions/question/annotation-on-axis

For your convenience I have re-written it out below and translated for the BoxAnnotation case.

Method #1 Using Annotations API

The following code will place an Annotation on the chart at a given X1X2 Y1Y2 value. In this method the SciChart Annotations API takes care of placement of the annotation as the chart resizes and VisibleRange changes.

   // This will display a BoxAnnotation between the dates of 1st Jan 2015 and 1st Feb 2015
   // and between Y-values 123 and 234. 
   // It will resize and move as you zoom and pan the chart
   // It assumes you have a XAxis = DateTimeAxis
   // For other axis types, the X1 type must change
   // 
   // e.g. CategorydateTimeAxis, use X1X2 = *index to the data*
   // e.g. NumericAxis, use X1X2 = double values
    var boxAnnotation = new BoxAnnotation();
    boxAnnotation.X1 = new DateTime(2015, 01, 01); // This is an X-data value
    boxAnnotation.X2 = new DateTime(2015, 02, 01);
    boxAnnotation.Y1 = 123.0; // This is a Y-data value
    boxAnnotation.Y1 = 234.0;
    sciChartSurface.Annotations.Add(boxAnnotation);

Method #2 Using SciChartSurface.ModifierSurface

Using this method you can declare any UIElement and place it on the SciChartSurface.ModifierSurface, using the attached properties Canvas.SetLeft() and Canvas.SetTop() to control placement manually.

You will be responsible for updating the position of the UIElement as the chart resizes and VisibleRange changes. To convert data to pixel coordinates, see our article [Convert Pixel to Data Coordinates][1]

 // Creates a box annotation with 100 pixel width and height
 // places over the chart at pixel coordinate X=100, Y=10
 // Does not move as you zoom and pan the chart
 // Does not need to be a BoxAnnotation, can be any UIElement
 var boxAnnotation = new BoxAnnotation() { Background = Brushes.Gray, Width= 100, Height=100 };
 Canvas.SetLeft(boxAnnotation , 100); // These are pixel coords
 Canvas.SetTop(boxAnnotation , 10);
 sciChartSurface.ModifierSurface.Children.Add(boxAnnotation );
  • David T
    Thank you Andrew,Reading through this, this demonstrates the placement of the BoxAnnotation via datapoints that we already know of.What I am looking to do is to allow a user to "Dynamically draw" the BoxAnnotation onto a SciStockChart inside a SciChartGroup.What I mean by this is to allow the user to Point and Click on the SciStockChart (a panel in the SciChartGroup) and free hand draw the BoxAnnotation.Is this possible? I remember speaking with you at the very beginning that you said this was possible, however I am still confused. Could you please enlighten this part for me? I need user interaction to create the BoxAnnotation.Thank you
  • Andrew
    We have a modifier called the AnnotationCreationModifier which does this and also an example in our examples suite. I suggest taking a look at that!
  • David T
    Andrew, your link https://www.scichart.com/questions/question/annotation-on-axis doesn't seem to be working. could you please fix.
  • David T
    Ok, So, I should be looking at the AnnotationCreationModifier instead of the CustomModifier? Can these modifiers be placed in the same group, e.g. AnnotationCreationModfiers with a CustomModifier such as SimpleRolloverModifier etc...?
  • Andrew
    It really depends, if you want to customize the placement then you will need your own modifier. If you are happy with our implementation, you can use that! Ultimately, all you need to do is a.) handle mouse events, b.) place UIElements on a canvas. We have many ways to achieve the same thing as there are many different things that users request. We also have APIs to convert between pixel and data coordinates (google it, it will come up top link). I hope I've given you enough pointers to go in the right direction.
  • You must to post comments
0
0

Hi there,

There is SourceObject property in EventTrigger which should be bound to source of event in such case.

Could you please try this code:

<s:AnnotationCreationModifier>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="AnnotationCreated" SourceObject="{Binding RelativeSource={RelativeSource AncestorType={x:Type s:AnnotationCreationModifier}}}">
            <i:InvokeCommandAction Command="{Binding CommandProperty}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</s:AnnotationCreationModifier>

Please try it out and let us know if this works for you too.
Hope this helps,

Best regards,
Taras B.
SciChart Developer

  • You must to post comments
Showing 4 results
Your Answer

Please first to submit.