John Doe John Doe - 5 months ago 255
Vb.net Question

Chart Y axis switch between autoscale and manual range

I want to create a chart such that the user can choose to autoscale the y axis and also be able to manually change the axis at runtime. I am able to autoscale until the y Axis hasnt been changed using the updowns, however as soon I change any up down, the autoscale is unresponsive.

private void numUD_Graph_Ymax_ValueChanged(object sender, EventArgs e)
{
try
{
int newmax = (int)numUD_Graph_Ymax.Value;
int allowedmin = (int)numUD_Graph_Ymax.Minimum;
int allowedmax = (int)numUD_Graph_Ymax.Maximum;

if (newmax >= allowedmin && newmax <= allowedmax && newmax > chart.ChartAreas[0].AxisY.Minimum)
{
chart.ChartAreas[0].AxisY.Maximum = newmax;
chart.Update();
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString());
}
}

private void numUD_Graph_Ymin_ValueChanged(object sender, EventArgs e)
{
try
{
int newmin = (int)numUD_Graph_Ymin.Value;
int allowedmin = (int)numUD_Graph_Ymin.Minimum;
int allowedmax = (int)numUD_Graph_Ymin.Maximum;

if (newmin >= allowedmin && newmin <= allowedmax && newmin < chart.ChartAreas[0].AxisY.Maximum)
{
chart.ChartAreas[0].AxisY.Minimum = newmin;
chart.Update();
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString());
}
}


And this is my button handler for autoscaling visible data:

private void btn_AutoSize_Click(object sender, EventArgs e)
{
chart.ChartAreas[0].RecalculateAxesScale();
chart.Update();
updateUI();

}
private void updateUI()
{
numUD_Graph_Xmin.Value = (decimal)chart.ChartAreas[0].AxisX.Minimum;
numUD_Graph_Xmax.Value = (decimal)chart.ChartAreas[0].AxisX.Maximum;
numUD_Graph_XInterval.Value = (decimal)chart.ChartAreas[0].AxisX.Interval;
numUD_Graph_Ymin.Value = (decimal)chart.ChartAreas[0].AxisY.Minimum;
numUD_Graph_Ymax.Value = (decimal)chart.ChartAreas[0].AxisY.Maximum;

}


Where am I going wrong? How do I autoscale and load the new coordiates in the numeric up downs while also allowing the user to further modify the graph using the up downs.

TaW TaW
Answer

The key to bringing back the automatic scaling after having set one of the Axis's Minimum and/or Maximum values is to reset (all) those values:

private void btn_AutoSize_Click(object sender, EventArgs e)
{
    chart.ChartAreas[0].AxisX.Minimum = double.NaN;  /// <-- this is the magic 'number'
    chart.ChartAreas[0].AxisX.Maximum = double.NaN;
    chart.ChartAreas[0].AxisY.Minimum = double.NaN;
    chart.ChartAreas[0].AxisY.Maximum = double.NaN;


 // not quite sure about these limes
 /*  
    chart.ChartAreas[0].RecalculateAxesScale();  
    chart.Update();
    updateUI();

 */

}

Notes:

  • RecalculateAxesScale shouldn't be necessary as you didn't code the Customize event.

  • updateUI(); it is really hard to to set those NumericUpDowns to helpful values since they only accept numbers and don't know a state 'unset' except being disabled.

I would drop the button for a CheckBox cbx_AutoRange {Text = "Automatic Range"} and actually disable the numUD when it changes to Checked. Upon unchecking it I would set the values to the current min/max values in the Series maybe like this:

private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
    if (checkBox1.Checked)
    {
        chart.ChartAreas[0].AxisX.Minimum = double.NaN;
        chart.ChartAreas[0].AxisX.Maximum = double.NaN;
        chart.ChartAreas[0].AxisX.Interval = double.NaN;
        chart.ChartAreas[0].AxisY.Minimum = double.NaN;
        chart.ChartAreas[0].AxisY.Maximum = double.NaN;

        numUD_Graph_Xmin.Enabled = false;
        numUD_Graph_Xmax.Enabled = false;
        numUD_Graph_XInterval.Enabled = false;
        numUD_Graph_Ymin.Enabled = false;
        numUD_Graph_Ymax.Enabled = false;

    }
    else
    {
        numUD_Graph_Xmin.Enabled = true;
        numUD_Graph_Xmin.Value = (decimal)chart1.Series[0].Points.FindMinByValue().XValue;
        numUD_Graph_Xmax.Value = (decimal)chart1.Series[0].Points.FindMaxByValue().XValue;
      //.. etc
      //.. etc

    }

}

Not sure why you have code for both axes if you only want to turn autoscaling up for only one?