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!
- tecman234 asked 11 years ago
- You must login to post comments
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
- Yuriy Zadereckiy answered 11 years ago
-
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 login to post comments
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
- Yuriy Zadereckiy answered 11 years ago
-
That did it! It works perfectly. Thank you!
- You must login to post comments
Please login first to submit.