Comment append d’autres axes Y à MSChart avec une échelle différente à gauche ou à droite

Je veux append 3 axes Y pour le graphique avec différentes échelles.

Je veux obtenir un axe x et un axe y différent. Je l’ai fait comme ci-dessous code mais je veux montrer un axe y comme dans la 2ème image que j’ai attachée ..

Mon code C # jusqu’à présent:

private void checkBoxUseMultipleYAxis_CheckedChanged(object sender, EventArgs e) { if (checkBoxUseMultipleYAxis.Checked) { // Set custom chart area position chart1.ChartAreas["ChartArea1"].Position = new ElementPosition(25, 10, 68, 85); chart1.ChartAreas["ChartArea1"].InnerPlotPosition = new ElementPosition(10, 0, 90, 90);`` // Create extra Y axis for second and third series CreateYAxis(chart1, chart1.ChartAreas["ChartArea1"], chart1.Series["Current"], 13, 8); CreateYAxis(chart1, chart1.ChartAreas["ChartArea1"], chart1.Series["Capacity"], 22, 8); } else { // Set default chart areas chart1.Series["Current"].ChartArea = "ChartArea1"; chart1.Series["Capacity"].ChartArea = "ChartArea1"; // Remove newly created series and chart areas while (chart1.Series.Count > 3) { chart1.Series.RemoveAt(3); } while (chart1.ChartAreas.Count > 1) { chart1.ChartAreas.RemoveAt(1); } // Set default chart are position to Auto chart1.ChartAreas["ChartArea1"].Position.Auto = true; chart1.ChartAreas["ChartArea1"].InnerPlotPosition.Auto = true; } } public void CreateYAxis(Chart chart, ChartArea area, Series series, float axisOffset, float labelsSize) { // Create new chart area for original series ChartArea areaSeries = chart.ChartAreas.Add("ChartArea_" + series.Name); areaSeries.BackColor = Color.Transparent; areaSeries.BorderColor = Color.Transparent; areaSeries.Position.FromRectangleF(area.Position.ToRectangleF()); areaSeries.InnerPlotPosition.FromRectangleF(area.InnerPlotPosition.ToRectangleF()); areaSeries.AxisX.MajorGrid.Enabled = false; areaSeries.AxisX.MajorTickMark.Enabled = false; areaSeries.AxisX.LabelStyle.Enabled = false; areaSeries.AxisY.MajorGrid.Enabled = false; areaSeries.AxisY.MajorTickMark.Enabled = false; areaSeries.AxisY.LabelStyle.Enabled = false; areaSeries.AxisY.IsStartedFromZero = area.AxisY.IsStartedFromZero; series.ChartArea = areaSeries.Name; // Create new chart area for axis ChartArea areaAxis = chart.ChartAreas.Add("AxisY_" + series.ChartArea); areaAxis.BackColor = Color.Transparent; areaAxis.BorderColor = Color.Transparent; areaAxis.Position.FromRectangleF(chart.ChartAreas[series.ChartArea].Position.ToRectangleF()); areaAxis.InnerPlotPosition.FromRectangleF(chart.ChartAreas[series.ChartArea].InnerPlotPosition.ToRectangleF()); // Create a copy of specified series Series seriesCopy = chart.Series.Add(series.Name + "_Copy"); seriesCopy.ChartType = series.ChartType; foreach (DataPoint point in series.Points) { seriesCopy.Points.AddXY(point.XValue, point.YValues[0]); } // Hide copied series seriesCopy.IsVisibleInLegend = false; seriesCopy.Color = Color.Transparent; seriesCopy.BorderColor = Color.Transparent; seriesCopy.ChartArea = areaAxis.Name; // Disable drid lines & tickmarks areaAxis.AxisX.LineWidth = 0; areaAxis.AxisX.MajorGrid.Enabled = false; areaAxis.AxisX.MajorTickMark.Enabled = false; areaAxis.AxisX.LabelStyle.Enabled = false; areaAxis.AxisY.MajorGrid.Enabled = false; areaAxis.AxisY.IsStartedFromZero = area.AxisY.IsStartedFromZero; areaAxis.AxisY.LabelStyle.Font = area.AxisY.LabelStyle.Font; // Adjust area position areaAxis.Position.X -= axisOffset; areaAxis.InnerPlotPosition.X += labelsSize; } }; 

Donc je reçois une sortie comme ça

mais je veux ajuster cette sortie comme ça

C’est une question intéressante avec un morceau de code assez compliqué qui résout un problème que je n’ai jamais remarqué.

Parlons d’abord des bases.

Dans un graphique, vous pouvez append plusieurs séries de données à la même zone. Tant que les gammes de valeurs y sont plus ou moins les mêmes, il n’y a généralement pas de problème. Mais s’ils ne le sont pas, l’axe des y est redimensionné pour que toutes les valeurs tiennent dans la zone du graphique. Cela signifie que les séries avec de petites gammes vont être écrasées. Voici un exemple:

entrez la description de l'image ici

En plus des valeurs y illisibles pour toutes les séries sauf la série orange, nous constatons également qu’il n’y a qu’un seul titre d’axe; si cela s’applique à toutes les séries, ok; mais si ce n’est pas le cas: mieux vaut laisser tomber ..

(Parfois, définir l’axe des ordonnées pour qu’il soit logarithmique peut aider, mais généralement, cela ne ferait que compliquer les choses et ne pas aider du tout.)

Cela appelle plus d’axes. En fait, il y a un axe supplémentaire intégré , juste là pour répondre: chaque zone de graphique peut avoir un axe y principal à gauche et un autre, appelé AxisY2secondaireAxisY2 à droite.

Vous pouvez l’activer et y associer une série:

 chart1.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True; chart1.Series[1].YAxisType = AxisType.Secondary; 

C’est bien et fonctionne bien. Mais notre exemple appelle plus de 2 axes y .. ce qui est exactement ce que le code que vous avez trouvé fournit.

Regardons d’abord les résultats:

entrez la description de l'image ici

C’est sympa; Nous pouvons maintenant voir en quoi les plages varient de 0 - 30 à 0 - 120 , de -20 - 30 et enfin de 0 - 1200 .

Mais tous les axes étant ajoutés à gauche, ils s’éloignent de plus en plus de la zone de tracé. D’où votre question ..

J’ai trouvé plus facile de développer le code que vous avez trouvé au lieu d’écrire une meilleure version à partir de zéro. Cela implique que la plupart des problèmes avec le code sont toujours présents:

  • Non modularisé
  • Les routines dépendent de valeurs “magiques”
  • Trouver ces valeurs par essais et erreurs est fastidieux

J’ai ajouté deux parameters à la méthode CreateYAxis ; l’un définit la largeur des zones d’axe ajoutées et l’autre bascule en les ajoutant à gauche ou à droite.

Regardons d’abord le résultat: entrez la description de l'image ici

Maintenant pour le code modifié:

 public void CreateYAxis(Chart chart, ChartArea area, Series series, float axisX, float axisWidth, float labelsSize, bool alignLeft) { chart.ApplyPaletteColors(); // (*) // Create new chart area for original series ChartArea areaSeries = chart.ChartAreas.Add("CAs_" + series.Name); areaSeries.BackColor = Color.Transparent; areaSeries.BorderColor = Color.Transparent; areaSeries.Position.FromRectangleF(area.Position.ToRectangleF()); areaSeries.InnerPlotPosition.FromRectangleF(area.InnerPlotPosition.ToRectangleF()); areaSeries.AxisX.MajorGrid.Enabled = false; areaSeries.AxisX.MajorTickMark.Enabled = false; areaSeries.AxisX.LabelStyle.Enabled = false; areaSeries.AxisY.MajorGrid.Enabled = false; areaSeries.AxisY.MajorTickMark.Enabled = false; areaSeries.AxisY.LabelStyle.Enabled = false; areaSeries.AxisY.IsStartedFromZero = area.AxisY.IsStartedFromZero; // associate series with new ca series.ChartArea = areaSeries.Name; // Create new chart area for axis ChartArea areaAxis = chart.ChartAreas.Add("CA_AxY_" + series.ChartArea); areaAxis.BackColor = Color.Transparent; areaAxis.BorderColor = Color.Transparent; RectangleF oRect = area.Position.ToRectangleF(); areaAxis.Position = new ElementPosition(oRect.X, oRect.Y, axisWidth, oRect.Height); areaAxis.InnerPlotPosition .FromRectangleF(areaSeries.InnerPlotPosition.ToRectangleF()); // Create a copy of specified series Series seriesCopy = chart.Series.Add(series.Name + "_Copy"); seriesCopy.ChartType = series.ChartType; seriesCopy.YAxisType = alignLeft ? AxisType.Primary : AxisType.Secondary; // (**) foreach (DataPoint point in series.Points) { seriesCopy.Points.AddXY(point.XValue, point.YValues[0]); } // Hide copied series seriesCopy.IsVisibleInLegend = false; seriesCopy.Color = Color.Transparent; seriesCopy.BorderColor = Color.Transparent; seriesCopy.ChartArea = areaAxis.Name; // Disable grid lines & tickmarks areaAxis.AxisX.LineWidth = 0; areaAxis.AxisX.MajorGrid.Enabled = false; areaAxis.AxisX.MajorTickMark.Enabled = false; areaAxis.AxisX.LabelStyle.Enabled = false; Axis areaAxisAxisY = alignLeft ? areaAxis.AxisY : areaAxis.AxisY2; // (**) areaAxisAxisY.MajorGrid.Enabled = false; areaAxisAxisY.IsStartedFromZero = area.AxisY.IsStartedFromZero; areaAxisAxisY.LabelStyle.Font = area.AxisY.LabelStyle.Font; areaAxisAxisY.Title = series.Name; areaAxisAxisY.LineColor = series.Color; // (*) areaAxisAxisY.TitleForeColor = Color.DarkCyan; // (*) // Adjust area position areaAxis.Position.X = axisX; areaAxis.InnerPlotPosition.X += labelsSize; } 

J’ai ajouté un petit code pour que les axes aient les couleurs de la série. (*) Le alignLeft , lorsqu’il est alignLeft false, sélectionne l’axe secondaire au lieu de l’axe principal . (**)

Les numéros nécessaires sont utilisés lors de l’appel de la méthode dans l’événement case à cocher.

Voici les lignes et les chiffres utilisés pour mes captures d’écran:

D’abord le normal ..

 // Set custom chart area position ChartArea ca = chart1.ChartAreas["ChartArea1"]; ca.Position = new ElementPosition(23, 10, 77, 85); ca.InnerPlotPosition = new ElementPosition(12, 0, 67, 90); // Create extra Y axis for some series CreateYAxis(chart1, ca, chart1.Series["Current"], 5, 9, 8, true); CreateYAxis(chart1, ca, chart1.Series["Capacity"], 13, 9, 8, true); CreateYAxis(chart1, ca, chart1.Series["testing"], 21, 9, 8, true); 

..then celui avec un axe de série ajouté à droite:

 // Set custom chart area position ChartArea ca = chart1.ChartAreas["ChartArea1"]; ca .Position = new ElementPosition(15, 10, 83, 85); ca .InnerPlotPosition = new ElementPosition(12, 0, 67, 90); // Create extra Y axis for some series CreateYAxis(chart1,ca , chart1.Series["Current"], 5, 9, 8, true); CreateYAxis(chart1, ca , chart1.Series["Capacity"], 13, 9, 8, true); CreateYAxis(chart1, ca , chart1.Series["testing"], 64, 21, 8, false); 

Notez que la twig else de l’événement de case à cocher tente de supprimer les zones de graphique supplémentaires. Il a un numéro codé en dur 3 ; et le code d’inversion n’est pas assez stable!

Une courte description de ce que le code lui-même fait:

Il ajoute deux zones de graphique supplémentaires pour chaque “axe de série” supplémentaire:

  • Un pour associer la série originale à. Celui-ci doit toujours avoir la même position et la même taille que la zone de graphique d’origine! Son but est de permettre aux graphiques d’être redimensionnés au maximum, ce qu’il fera, puisqu’aucune autre série n’est associée à cette nouvelle zone de graphique. Les graphiques restnt visibles mais toutes les autres parties, comme les bordures d’axes, etc.

  • L’autre montrera l’axe. Ici tout sauf l’axe est invisible; et pour remplir l’axe, les points de la série originale sont copiés dans une nouvelle série, qui est associée à cette zone de graphique.

Remarque finale sur l’utilisation: L’utilisation totale dépend toujours des chiffres que vous utilisez pour disposer les zones de graphique! J’ai moi-même écrit un petit outil d’aide que vous pouvez télécharger si cela vous intéresse. La voici au travail:

entrez la description de l'image ici