Hey guys,
I was working off an example I found on these forums to allow users to interact with the chart using the mouse. I capture the usual mouse events and as the mouse moves, I update the datapoint's value (I'm using a 2D line chart).
However, there is a problem I am running into. As I drag a value, the y-axis value might change (sinve the y-axis has AutoRange set to true). The problem is when the range of the y-axis changes, the datapoint appears in a different position on the screen, and is no longer under the mouse. It is easy to see this. Just slowly drag a datapoint. It will be under the mouse until the range of the y-axis is changed. Then the datapoint is "moved" and the next mouse move causes it to jump ahead. This causes erratic movements when using the mouse to change a value.
Is there a way to have the datapoints move smoothly along with the mouse when AutoRange is set to true?
Maybe you should try disabling the autorange during the drag? Or do you need the range to adjust while someone is moving the point? You may need to take control over calculating the ranges manually and then you can make sure the point stays under the mouse during the range change.
Hey Graham.
Thanks for taking the time to help me out. I tried to calculate the ranges myself but couldn't get it to work quite right. I can't get the datapoint to stay under the mouse.
Do you think you can provide a small, sample app demonstrating how one might do this?
Thank you.
It looks like that could be unintended that the default style is not included. I'm looking into it. Do you have Expression Blend? That tool gives a neat way of extracting the default style for a control and helps you modify it, to boot. If not we can pass the style along.
-Graham
sorry, wrong thread.
This code disables the axis ranges during the drag. Does that help?
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private DataPoint _dragging = null; private void theChart_MouseDown(object sender, MouseButtonEventArgs e) { var test = theChart.HitTest(e); var dp = test.SelectedObject as DataPoint; if (dp == null) { return; } _dragging = dp; DisableAutoRange(); } private void DisableAutoRange() { double xMin; double yMin; double xMax; double yMax; double yUnit; double xUnit; theChart.GetAxisRange(AxisType.PrimaryX, out xMin, out xMax, out xUnit); theChart.GetAxisRange(AxisType.PrimaryY, out yMin, out yMax, out yUnit); var xAxis = theChart.Axes.Where( (a) => a.AxisType == AxisType.PrimaryX) .FirstOrDefault(); var yAxis = theChart.Axes.Where( (a) => a.AxisType == AxisType.PrimaryY) .FirstOrDefault(); xAxis.Minimum = xMin; xAxis.Maximum = xMax; xAxis.Unit = xUnit; yAxis.Minimum = yMin; yAxis.Maximum = yMax; yAxis.Unit = yUnit; xAxis.AutoRange = false; yAxis.AutoRange = false; } private void theChart_MouseMove(object sender, MouseEventArgs e) { if (_dragging == null) { return; } Point pos = e.GetPosition(theChart); double xMin; double yMin; double xMax; double yMax; double yUnit; double xUnit; theChart.GetAxisRange(AxisType.PrimaryX, out xMin, out xMax, out xUnit); theChart.GetAxisRange(AxisType.PrimaryY, out yMin, out yMax, out yUnit); double xPixelMin = theChart.GetPosition(AxisType.PrimaryX, xMin); double xPixelMax = theChart.GetPosition(AxisType.PrimaryX, xMax); double yPixelMin = theChart.GetPosition(AxisType.PrimaryY, yMin); double yPixelMax = theChart.GetPosition(AxisType.PrimaryY, yMax); double pX = (pos.X - xPixelMin) / (xPixelMax - xPixelMin); double pY = (pos.Y - yPixelMin) / (yPixelMax - yPixelMin); System.Diagnostics.Debug.WriteLine(pX + "," + pY); double currX = (pX * (xMax - xMin)) + xMin; double currY = (pY * (yMax - yMin)) + yMin; var xParam = _dragging.ChartParameters.Where( (p) => p.Type == ChartParameterType.ValueX) .FirstOrDefault(); var yParam = _dragging.ChartParameters.Where( (p) => p.Type == ChartParameterType.ValueY) .FirstOrDefault(); if (xParam != null) { xParam.Value = currX; } if (yParam != null) { yParam.Value = currY; } } private void theChart_MouseUp(object sender, MouseButtonEventArgs e) { _dragging = null; RenableAutoRange(); } private void RenableAutoRange() { var xAxis = theChart.Axes.Where( (a) => a.AxisType == AxisType.PrimaryX) .FirstOrDefault(); var yAxis = theChart.Axes.Where( (a) => a.AxisType == AxisType.PrimaryY) .FirstOrDefault(); xAxis.AutoRange = true; yAxis.AutoRange = true; } }
Is there an updated example of using the mouse to move datapoints? I'm using 2014.1 and a lot of these methods on the chart object don't exist anymore - or have been moved somewhere else. Note: I'm using the Winform control not the WPF.
This sample was for the XamChart, which was never available in Windows Forms (unlike the XamDataChart, which shares an API with UltraDataChart).
Attached is a little sample with a basic implementation of drag and drop for an UltraDataChart.