Reputation: 11
Is there any way I can click on a MSChart and drag it left/right in order to scroll the chart to the right/left. The idea is to drag the chart instead of dragging the chart's scroll bar. The reason I'm not simply using the scroll bar is because I was asked to add this feature (bosses and their demands..). Btw, I'm using C# and winforms. Hope I was clear enough. Thanks!!
Upvotes: 1
Views: 1808
Reputation: 54433
Yes this is possible.
One issue is that you can't use the normal zooming/scrolling mechanism as this itself works by dragging over the chart.
Instead pass it by and code two mouseevents and use the Axis.PixelPositionToValue
function to access the data values.
First we store the data value of the clicked location:
double mDown = double.NaN;
private void chart1_MouseDown(object sender, MouseEventArgs e)
{
Axis ax = chart1.ChartAreas[0].AxisX;
mDown = ax.PixelPositionToValue(e.Location.X);
}
Then we calculate the old range how far the Axis.Minimum
has moved and adapt Minimum
and Maximum
:
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
if (!e.Button.HasFlag(MouseButtons.Left)) return;
Axis ax = chart1.ChartAreas[0].AxisX;
double range = ax.Maximum - ax.Minimum;
double xv = ax.PixelPositionToValue(e.Location.X);
ax.Minimum -= xv - mDown;
ax.Maximum = ax.Minimum + range;
}
You will want to add a few checks to prevent dragging too far left or right..
Note that the code assumes that you have set Minimum
and Maximum
!
Also note that you will want to take control over the format of the x-axis labels so they don't make the chart jump around by having lot of fractional digits.
Or, depending on your data, you may want to set the step to a multiple of some value, suitable for your interval or in my case simply to ints
:
ax.Minimum -= (int)(xv - mDown) ;
If you need to have the scrollbars visible you can still use the above code; but you need to replace this
ax.Minimum -= (int)(xv - mDown);
ax.Maximum = ax.Minimum + range;
by this:
double oldPos = ax.ScaleView.Position;
ax.ScaleView.Position -= (xv - mDown);
However this does interfer with the normal scolling. You can insert checks to make sure you are not hitting the scrollbar like this:
RectangleF ipar = InnerPlotPositionClientRectangle(chart1, chart1.ChartAreas[0]);
if (ipar.Contains(e.Location))
{
..
..
..but it still acts up here. So either or seems to work best.
The InnerPlotPositionClientRectangle
is defined here.
Upvotes: 2