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!

Please note: SciChart team will only answer questions from customers with active support subscriptions. Expired support questions will be ignored. If your support status shows incorrectly, contact us and we will be glad to help.

0
0

hi,
I have multiple stock charts, and each chart has a different data sample time. my GlobalCursorModifierEx should force all charts to display the cursor at the DateTime/price point that matches the chart the mouse is over.
I have two things that don’t work right:
1. The vertical line displays on all charts, and follows the mouse on the chart that has the cursor, but it has no axis label except on the chart the mouse is over.
2. The horizontal cursor line only displays on the chart the mouse is over.

Here are the GlobalCursorModifierEx suspect methods:

    /// <summary>
    /// use my mouse position if mouse is over my chart, and tell other charts of it's new position
    /// </summary>
    /// <param name="e"></param>
    public override void OnModifierMouseMove(ModifierMouseArgs e)
    {
        if (useMyMousePosition && VM !=null)
        {
            base.OnModifierMouseMove(e);
            //send mediator message to all other charts, so they can move their cursor to match mine
            Point mousePoint = e.MousePoint;//GetPosition(view.ChartSurface.ModifierSurface as UIElement);
            var mouseDate = VM.GetMouseTime(mousePoint);
            var mousePrice = VM.GetMousePrice(mousePoint);
            var gc = new GlobalCursor(mouseDate, mousePrice, 0, VM.ChartTF, mouseDate);
            //Update the global cursor and send new position to all charts (including this chart)
            //send Cinch event to other charts so they can move their global cursor too
              logger.Debug("updating other charts to {0} {1}", mouseDate, mousePrice);
          Mediator.Instance.NotifyColleagues<GlobalCursor>("UpdGlobalCursorCommand", gc);
        }
    }

    protected override void OnParentSurfaceMouseEnter()
    {
        useMyMousePosition = true;
        base.OnParentSurfaceMouseEnter();
    }

    protected override void OnParentSurfaceMouseLeave()
    {
        useMyMousePosition = false;
        base.OnParentSurfaceMouseLeave();
    }

    /// <summary>
    /// cursor moved to a new position on another chart
    /// </summary>
    [MediatorMessageSink("UpdGlobalCursorCommand")]
    private void UpdGlobalCursorMessageSink(GlobalCursor gc)
    {
        if (useMyMousePosition)
        {
            //do nothing, as this move originated on my chart, so my OnModifierMouseMove() already took care of it
        }
        else //mouse is over another chart, so set my cursor to match it's position
        {
            //if my view is loaded (VM is set) find my chart data index that corresponds to the time of the cursor position
            if (VM != null)
            {
                var xCoordCalculator = ParentSurface.XAxis.GetCurrentCoordinateCalculator();
                var XcoordCalc = ParentSurface.XAxis.GetCurrentCoordinateCalculator() as ICategoryCoordinateCalculator;
                var YcoordCalc = ParentSurface.YAxis.GetCurrentCoordinateCalculator() as ICoordinateCalculator<double>;
                if (XcoordCalc != null && YcoordCalc !=null) //might be null if mouse is moved while app is loading
                {
                    //determine the closest bar to the cursor timestamp
                    var closestBarTimeStamp = dataServerDomSvc.BarTimeForTimeStamp(gc.BarTime, gc.chartTF,
                                                                                   VM.ChartTF);
                    var myIndex = XcoordCalc.TransformDataToIndex(closestBarTimeStamp);
                    //convert dateTime,double to pixel coordinates
                    var mouseX = xCoordCalculator.GetCoordinate(myIndex);
                    var mouseY = YcoordCalc.GetCoordinate(gc.y);

                    //set my cursor position
                    logger.Debug("{0} {1} setting my cursor to {2} @{3}; x:{4}, y:{5}", VM.ChartSymbol, VM.ChartTF,
                                 closestBarTimeStamp, gc.y, mouseX, mouseY);
                    overrideArgs = new ModifierMouseArgs(new Point(mouseX, mouseY),
                                                         MouseButtons.None, MouseModifier.None, 0, false, null)
                        {
                            Handled = false
                        };
                    base.OnModifierMouseMove(overrideArgs);
                }
            }
        }
    }

thanks for your help!

  • You must to post comments
0
0

Hi there,

Thank you for the screenshots and explanation, it helps a lot! Current behavior is default behavior for mouse synchronized modifiers, you need to change the custom modifier in such a way:

   public class CursorModifierEx: CursorModifier
    {
       public override void OnModifierMouseMove(ModifierMouseArgs e)
       {
           // indicates that event occurs for chart
           // which is not hovered by mouse cursor,
           // so calculate and assign new coordinate
           if(!e.IsMaster)
           {
             // calculate new point here

             e.MousePoint = // assign new point
           }

           e.IsMaster = true;

           base.OnModifierMouseMove(e);
       }
    }

..and share modifiers across the charts as demonstrated in Sync Multi Chart example, using MouseManager.MouseEventGroup attached property.

The key point is to set ModifierMouseArgs.IsMaster = true, which indicates that event occurs on the chart which mouse cursor is over.

Please, let us know if this helps you!

Best regards,
Yuriy

  • tecman234
    Yuriy, The 3 charts are 3 instantiations of a user control backed by a chartViewModel. So the synchronization is accross 3 separate user controls, not multiple charts within the same user control. So the chart that IsMaster needs to do the calculation of the DateTime/yValue and send that to the other charts. (In otherwords, the OnModifierMouseMove on the 'slave' charts can't do the position calculation directly, because it doesn't know the current DateTime/yValue under the mouse). So I still don't understand why the code I posted doesn't work. With the debugger, I see that the master chart sends the UpdGlobalCursorMessageSink event, and the 2 slave charts consume it, and invoke their overridden OnModifierMouseMove with what looks like reasonable pixel coordinates. Even if I have an error in the Yvalue calculation, I would think the vertical cursor on the slave charts should still display it's axis label.
  • You must to post comments
0
0

Hi,

Please, try to change 1 argument passed into ModifierMouseArgs ctor inside the UpdGlobalCursorMessageSink method:

 overrideArgs = new ModifierMouseArgs(new Point(mouseX, mouseY),
                                                     MouseButtons.None, MouseModifier.None, 0, true, null)

It seems to me you should pass “True” to notify modifier that it needs to handle the event as those which comes from main chart.

Let us know if this helps!

Best regards,
Yuriy

  • tecman234
    That did it! It works perfectly. Thank you!
  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.