0
votes

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

1
Hm, you want them to be aligned yet scroll them independently? Doesn't that simply mean you need to keep the scale of the x-axis equal?TaW
sorry for ambiguous expression. I mean, I want all to be aligned. and I want to scroll the others (at once) except the first chart area. I'm not sure what is 'simply keep the scale' but, what i want is the answer's gif in the above link.Lee
Well if you want one (main) chartarea to stay put, simply don't write code for it in the AxisViewChanged event!TaW
By Scale I mean basically the amount of data shown on an axis. You can control it by setting minimum&Maximum. After zooming it is the .ScaleView.ViewMinimum&Maximum.TaW
Oops you thought the 'scroll' is horizontal, right? I didn't specify. My apologizes... The scroll is vertical scroll. I updated my question with snapshot.Lee

1 Answers

3
votes

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!