• No results found

This way, you no longer need to set the plot area inside Form1, making the program more readable

}

Then, add this method to the AddChartStyle method:

public void AddChartStyle(Graphics g) {

SetPlotArea(g);

// Draw TotalChartArea, ChartArea, and PlotArea:

Pen aPen = new Pen(ChartBorderColor, 1f);

SolidBrush aBrush = new SolidBrush(ChartBackColor);

g.FillRectangle(aBrush, ChartArea);

g.DrawRectangle(aPen, ChartArea);

aPen = new Pen(PlotBorderColor, 1f);

aBrush = new SolidBrush(PlotBackColor);

g.FillRectangle(aBrush, PlotArea);

g.DrawRectangle(aPen, PlotArea);

……

……

}

This way, you no longer need to set the plot area inside Form1, making the program more readable.

Modifying Form1 Class

Suppose we want to create a 2x2 sub-chart layout. Each sub-chart has its own chart styles. The following is the sample code of the Form1 class that creates such 2x2 sub-charts:

using System;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Collections;

using System.Windows.Forms;

namespace Example3_7 {

public partial class Form1 : Form {

private SubChart sc;

private DataCollection dc1;

private DataCollection dc2;

private DataCollection dc3;

private DataCollection dc4;

private ChartStyle cs1;

private ChartStyle cs2;

private ChartStyle cs3;

private ChartStyle cs4;

private Legend lg;

public Form1()

{

InitializeComponent();

SetStyle(ControlStyles.ResizeRedraw, true);

This.BackColor = Color.White;

// Set Form1 size:

this.Width = 650;

this.Height = 600;

// Sub Chart parameters:

sc = new SubChart(this);

sc.TotalChartBackColor = Color.White;

sc.Margin = 20;

sc.Rows = 2;

sc.Cols = 2;

// Parameters for sub-chart 1 (0, 0):

dc1 = new DataCollection();

cs1 = new ChartStyle(this);

cs1.TickFont = new Font("Arial", 7, FontStyle.Regular);

cs1.TitleFont = new Font("Arial", 10, FontStyle.Regular);

cs1.XLimMin = 0f;

cs1.XLimMax = 7f;

cs1.YLimMin = -1.5f;

cs1.YLimMax = 1.5f;

cs1.XTick = 1.0f;

cs1.YTick = 0.5f;

cs1.Title = "Sin(x)";

// Parameters for sub-chart 2 (0, 1):

dc2 = new DataCollection();

cs2 = new ChartStyle(this);

cs2.TickFont = new Font("Arial", 7, FontStyle.Regular);

cs2.TitleFont = new Font("Arial", 10, FontStyle.Regular);

cs2.XLimMin = 0f;

cs2.XLimMax = 7f;

cs2.YLimMin = -1.5f;

cs2.YLimMax = 1.5f;

cs2.XTick = 1.0f;

cs2.YTick = 0.5f;

cs2.Title = "Cos(x)";

// Parameters for sub-chart 3 (1, 0):

dc3 = new DataCollection();

cs3 = new ChartStyle(this);

cs3.TickFont = new Font("Arial", 7, FontStyle.Regular);

cs3.TitleFont = new Font("Arial", 10, FontStyle.Regular);

cs3.XLimMin = 0f;

cs3.XLimMax = 7f;

cs3.YLimMin = -0.5f;

cs3.YLimMax = 1.5f;

cs3.XTick = 1.0f;

cs3.YTick = 0.5f;

cs3.Title = "Sin(x)^2";

// Parameters for sub-chart 4 (1, 1):

dc4 = new DataCollection();

cs4 = new ChartStyle(this);

cs4.IsY2Axis = true;

cs4.IsXGrid = false;

cs4.IsYGrid = false;

cs4.TickFont = new Font("Arial", 7, FontStyle.Regular);

cs4.TitleFont = new Font("Arial", 10, FontStyle.Regular);

cs4.XLimMin = 0f;

cs4.XLimMax = 30f;

cs4.YLimMin = -20f;

cs4.YLimMax = 20f;

cs4.XTick = 5.0f;

cs4.YTick = 5f;

cs4.Y2LimMin = 100f;

cs4.Y2LimMax = 700f;

cs4.Y2Tick = 100f;

cs4.XLabel = "X Axis";

cs4.YLabel = "Y Axis";

cs4.Y2Label = "Y2 Axis";

cs4.Title = "With Y2 Axis";

lg = new Legend();

lg.IsLegendVisible = true;

lg.LegendPosition = Legend.LegendPositionEnum.SouthEast;

}

private void AddData(Graphics g) {

float x = 0f;

float y = 0f;

// Add Sin(x) data to sub-chart 1:

dc1.DataSeriesList.Clear();

DataSeries ds = new DataSeries();

ds.LineStyle.LineColor = Color.Red;

ds.LineStyle.Thickness = 2f;

ds.LineStyle.Pattern = DashStyle.Dash;

for (int i = 0; i < 50; i++) {

x = i / 5.0f;

y = (float)Math.Sin(x);

ds.AddPoint(new PointF(x, y));

}

dc1.Add(ds);

// Add Cos(x) data sub-chart 2:

dc2.DataSeriesList.Clear();

ds = new DataSeries();

ds.LineStyle.LineColor = Color.Blue;

ds.LineStyle.Thickness = 1f;

ds.SymbolStyle.SymbolType =

SymbolStyle.SymbolTypeEnum.OpenDiamond;

for (int i = 0; i < 50; i++)

{

x = i / 5.0f;

y = (float)Math.Cos(x);

ds.AddPoint(new PointF(x, y));

}

dc2.Add(ds);

// Add Sin(x)^2 data to sub-chart 3:

dc3.DataSeriesList.Clear();

ds = new DataSeries();

ds.LineStyle.IsVisible = false;

ds.SymbolStyle.SymbolType = SymbolStyle.SymbolTypeEnum.Dot;

ds.SymbolStyle.FillColor = Color.Yellow;

ds.SymbolStyle.BorderColor = Color.DarkCyan;

for (int i = 0; i < 50; i++) {

x = i / 5.0f;

y = (float)Math.Sin(x);

ds.AddPoint(new PointF(x, y * y));

}

dc3.Add(ds);

// Add y1 and y2 data to sub-chart 4:

dc4.DataSeriesList.Clear();

// Add y1 data:

ds = new DataSeries();

ds.LineStyle.LineColor = Color.Red;

ds.LineStyle.Thickness = 2f;

ds.LineStyle.Pattern = DashStyle.Dash;

ds.SeriesName = "x1*cos(x1)";

for (int i = 0; i < 20; i++) {

float x1 = 1.0f * i;

float y1 = x1 * (float)Math.Cos(x1);

ds.AddPoint(new PointF(x1, y1));

}

dc4.Add(ds);

// Add y2 data:

ds = new DataSeries();

ds.LineStyle.LineColor = Color.Blue;

ds.LineStyle.Thickness = 2f;

ds.SeriesName = "100 + 20*x2";

ds.IsY2Data = true;

for (int i = 5; i < 30; i++) {

float x2 = 1.0f * i;

float y2 = 100.0f + 20.0f * x2;

ds.AddPoint(new PointF(x2, y2));

}

dc4.Add(ds);

}

protected override void OnPaint(PaintEventArgs e) {

Graphics g = e.Graphics;

// Re-define TotalChartArea for resizing:

sc.TotalChartArea = this.ClientRectangle;

// Add data for all sub-charts:

AddData(g);

// Create sub-chart layout:

Rectangle[,] subchart = sc.SetSubChart(g);

// Create sub-chart 1:

cs1.ChartArea = subchart[0, 0];

cs1.AddChartStyle(g);

dc1.AddLines(g, cs1);

// Create sub-chart 2:

cs2.ChartArea = subchart[0, 1];

cs2.AddChartStyle(g);

dc2.AddLines(g, cs2);

// Create sub-chart 3:

cs3.ChartArea = subchart[1, 0];

cs3.AddChartStyle(g);

dc3.AddLines(g, cs3);

// Create sub-chart 4:

cs4.ChartArea = subchart[1, 1];

cs4.AddChartStyle(g);

dc4.AddLines(g, cs4);

lg.AddLegend(g, dc4, cs4);

g.Dispose();

} } }

It is apparent that the current Form1 class looks more like an application program. All of the chart styles, symbols, line styles, etc. are encapsulated in the other classes. In the Form1 class, you simply create various instances, set parameters, and add your data to the chart.

Let’s look at how the program works. First we create a SubChart object sc. Then we define four DataCollect objects and four ChartStyle objects, because we want to create a sub-chart plot with four sub-sub-charts, each using different DataCollection and ChartStyle. We also create a legend object which can be used in any sub-chart. Inside Form1’s constructor, we create the instance for the SubChart object and define the corresponding parameters. Here we set cs.Row = 2 and cs.Cols = 2 to create a 2X2 sub-chart layout. The code that follows is standard parameter settings for each sub-chart, such as those of the single chart program we created in the previous sections. In particular, sub-chart 4 has a Y2 axis, which demonstrates that each sub-chart can have its own chart style, and can even have two Y axes.

Inside the AddData method, we add various DataSeries object, ds, to the different data

collections, dc1, dc2, dc3, and dc4. Each dc has a different line and symbol style. Please note

that we re-create the ds instance when we add it to the different DataCollection objects with