Lee
Lee

Reputation: 11

C# - scroll down a Chart without first ChartArea

The results I want are one main chart and several sub charts which are synchronized with the main chart. (Sub charts must share the same x-axis with the main chart.)

At first, I tried it using multiple chartAreas. I can sync sub chartAreas with the main chartArea. (Using this: How to align two (or more) charts in size, scroll and grid) This one is what I want exactly. But I can't only vertical scroll the sub-chartAreas. If I scroll, all the charts are scrolled. I want to vertical scroll only sub-chartAreas. (to show the main chartArea at top anytime even when the scroll bar is down)

So, I reverse a decision to use multiple charts (not chart Areas). I can place them into TableLayoutPanel. One chart per row. Then, I cannot sync their x-axes...

Is there any way to sync an x-axis with multiple charts? Or to scroll only sub-chartAreas using multiple chartAreas?

By 'scroll' I mean Vertical scroll. See here:

enter image description here

Upvotes: 0

Views: 1617

Answers (1)

TaW
TaW

Reputation: 54433

From the image and the comments I gather that you actually want to scroll down a chart with several ChartArea but keep one fixed at the top.

((If that is so you should correct the question title!))

By default a Chart can only scroll the data within a zoomed ChartArea, not several ChartAreas within the Chart.

Here is an example of faking both ChartArea scrolling and freeezing the top ChartArea.

Here are the necessary steps:

  • We need a VerticalScrollbar control and anchor it to the right of the Chart.

  • We need to set its Minumum and Maximum fields to suitable values; I left the minimum at 0 and calculate the max with a few params..

  • Then we can code its Scroll event..:


private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
    float h = (100 - yOffTop - yOffBottom) / visibleCount;
    ChartArea main = chart1.ChartAreas[0];

    for (int i = 1; i < chart1.ChartAreas.Count; i++)
    {
        ChartArea ca = chart1.ChartAreas[i];
        ca.Position = new ElementPosition(0, h * i - vScrollBar1.Value + mainExtra, 80, h);
        ca.Visible = ca.Position.Y  >= main.Position.Bottom ;
    }
}

visibleCount controls how many ChartAreas are visible. In this example I have one for the year, fixed at the top and 12 more for the months..:

enter image description here

For this to work you need to set up the chart so that the chartareas are intialized in a suitable way.

I used this piece of code, do use your own code for stuff like right space (I left 20% for the legend) etc..:

    int visibleCount = 5;
    float yOffTop = 0;     // no extra top space for a chart title
    float yOffBottom = 0;  // no extra  bottom space either
    float mainExtra = 6;   // a few extra% for the main CA's axis labels

    private void Init_button_Click(object sender, EventArgs e)
    {
        chart1.Series.Clear();
        chart1.ChartAreas.Clear();
        chart1.BackColor = Color.Snow;
        float h = (100 - yOffTop - yOffBottom) / visibleCount;
        for (int i = 0; i < 13; i++)
        {
            float yOff = i != 0 ? mainExtra : 0;
            float yExtra = i == 0 ? mainExtra : 0;
            ChartArea ca = chart1.ChartAreas.Add("ca" + i);
            ca.Position = new ElementPosition(0, h * i + yOff , 80, h + yExtra);
            ca.BackColor = Color.FromArgb(i * 20, 255 - i * 3, 255);
            ca.AxisX.IntervalOffset = 1;

            Series s = chart1.Series.Add("s" + i);
            s.ChartArea = ca.Name;
            for (int j = 1; j < 30; j++)
            {
                s.Points.AddXY(j, rnd.Next(100) - rnd.Next(20));
            }
            chart1.ChartAreas[0].BackColor = Color.Silver;
            ca.AxisY.Title = i == 0 ? "Year" :
                                       DateTimeFormatInfo.CurrentInfo.GetMonthName(i);
            ca.AxisX.Enabled = (i == 0) ? AxisEnabled.True :  AxisEnabled.False;
        }
        vScrollBar1.Minimum = 0;// (int)( h);
        vScrollBar1.Maximum = (int)((chart1.ChartAreas.Count - visibleCount + 0.5f) * h
                                   + mainExtra );
    }

I draw extra rectangles around each CA, just for testing; do ignore them!

Note: Working with those percentages is always a little tricky and may take some tweaking!

Upvotes: 3

Related Questions