Using the charting control from System.Windows.Forms.DataVisualization.Charting.Chart
, I am making a scatter plot.
How can I constrain it so that the scale of the X axis is the same as the scale of the Y axis?
Simply setting the control itself to be square is insufficient, because it has internal margins for drawing and labeling the axes which are not equal.
I could pick a specific size and tweak it to be square, but it needs to be both square and resizable.
I've searched high and low in the documentation and in the property browser, but I can't find anything or think of any ways to do it in the resize event.
This is a good question but unfortunately there is no simple solution like locking the two
Axes
or setting one value..Let's start by looking at the relevant players:
The
Chart
control has an innerSize
calledClientSize
, which is theChart.Size
minus the borders. Both sizes are measured in pixels.Inside there may be one or more
ChartAreas
. Each has aPosition
which is of typeElementPosition
.Inside each
ChartArea
the is an area which is used for the actual drawing of the points; it is calledInnerPlotPosition
.ChartArea.Position
andChartArea.InnerPlotPosition
contain not just the location but also the size of the areas; all values are in percent of the outer area, ieChartArea.InnerPlotPosition
is relative to theChartArea.Position
andChartArea.Position
is relative to theChart.ClientSize
. All percentages go from0-100
.So the
ChartArea
includesLabels
andLegends
as well asAxes
andTickMarks
..What we want is to find a way to make the
InnerPlotArea
square, i.e. have the same width and height in pixels. The percentages won't do!Let's start with a few simple calculations; if these are the data we have..:
.. then these are the pixel sizes of the two areas:
Ideally we would like the
InnerPlotArea
to be square; since can't very well let the smaller side grow (or else the chart would overdraw,) we need to shrink the larger one. So the new pixel size of theInnerPlotArea
isWhat next? Since the
Chart.Size
has just been set, we don't want to mess with it. Nor should we mess with theChartArea
: It still needs space to hold theLegend
etc..So we change the size of the
InnerPlotArea
..:First create a class level variable to store the original values of the
InnerPlotPosition
:We will need it to keep the original percentages, i.e. the margins in order to use them when calculating the new ones. When we adapt the chart the then current ones will already have been changed/distorted..
Then we create a function to make the
InnerPlotArea
square, which wraps it all up:You would call the function after or during resizing.
Here the function is at work:
The original size:
Squeezed a little:
And made square again:
Note how the green
ChartArea
reserves enough space for theLabels
and theLegend
and how the automatic scaling for the axes still works.. But the X-Axis labels now don't fit in one row. Also note how theChartArea.BackColor
actually is the color of theInnerPlotArea
only!Note that you may have to refresh the variable
ipp0
to reflect the changed percentages, after making modification to theChartArea
layout like enlarging or moving or removingLegends
or changing the size or angle ofLabels
etc..Of course you can modify the function to pass in any other ratio to keep instead of keeping the plot area a square..