Nevron Forum

scrollbar with primary and secondary Y axes

https://www.nevron.com/Forum/Topic8272.aspx

By Jeremy Courbat - Wednesday, October 30, 2013

Hi every body,

First of all sorry for my bad English, it's not my main language.

So, I try to do a linear graph with a scroll bar for X axis and one other for Y axis.

That is OK, it works fine.

Now I want to add a secondary Y axis and that is the problem.
When I scroll on Y axis the secondary scale don't move but the data, based on the second axis, does so the data is no more "in front of" the scale.

I see 2 possibilities:
- create a second scroll bar for the secondary axis => this one move the axis but not the data and the primary scroll bar does the same than before. I probably do a mistake somewhere or something is missing.
- synchronise the secondary axis with the primary scroll bar => I didn't know how to do this.

For now, I don't really know if I will choose solution 1 or 2, so if it's possible tell me how to do both.

Thanks for all the reply.

EDIT: The 2 axis didn't have the same range, one is -1000 to 1000 the other is 0 to 100, I didn't know if it make a difference.
By Jeremy Courbat - Wednesday, October 30, 2013

OK, I found the solution 1 myself.

For the linear data which should display on secondary axis, I put the wrong setting.
- wrong:
M_Line2.DisplayOnAxis(StandardAxis.SecondaryY, False)
M_Line2.DisplayOnAxis(StandardAxis.SecondaryY, True)
- Correct:
M_Line2.DisplayOnAxis(StandardAxis.PrimaryY, False)
M_Line2.DisplayOnAxis(StandardAxis.SecondaryY, True)


So just need the "synchronise scroll bar" solution if it's possible.
By Nevron Support - Thursday, October 31, 2013

Hi Jeremy,

You can use the following approach to synchronize the Y axes when one of them zooms in:

1. Implement an event handler of the scale ruler changed event of the y axis that you zoom, which looks like:

void Scale_RulerRangeChanged(object sender, EventArgs e)
  {
   _NevronChart.Document.Calculate();
   _NevronChart.Document.RecalcLayout(_NevronChart.View.Context);

   NChart chart = _NevronChart.Charts[0];

   NRange1DD contentRange = chart.Axis(StandardAxis.PrimaryY).ViewRange;
   NRange1DD viewRange = chart.Axis(StandardAxis.PrimaryY).Scale.RulerRange;

   // compute factors
   double beginFactor = contentRange.GetValueFactor(viewRange.Begin);
   double endFactor = contentRange.GetValueFactor(viewRange.End);

   // then for all other y axes make sure their view range factor equals to begin/end factor
   if (beginFactor == 0.0 && endFactor == 1.0)
   {
    // disable zoom
    foreach (NAxis axis in chart.Axes)
    {
     if (axis.AxisId != (int)StandardAxis.PrimaryY && axis.AxisOrientation == AxisOrientation.Vertical)
     {
      axis.PagingView.Enabled = false;
     }
    }
   }
   else
   {
    // disable zoom
    foreach (NAxis axis in chart.Axes)
    {
     if (axis.AxisId != (int)StandardAxis.PrimaryY && axis.AxisOrientation == AxisOrientation.Vertical)
     {
      axis.PagingView.Enabled = true;

      // compute the new range based on factor
      NRange1DD axisContentRange = axis.ViewRange;
      double rangeLength = axisContentRange.End - axisContentRange.Begin;

      double begin = axisContentRange.Begin + beginFactor * rangeLength;
      double end = axisContentRange.Begin + endFactor * rangeLength;

      axis.PagingView.ZoomIn(new NRange1DD(begin, end), 0.0001);
     }
    }
   }

   _NevronChart.Refresh();
  }


Here the idea is to take the current zoom range in factor form - for example if the axis content range is 0, 100 and the axis is zoomed to 20, 40 - then the code computes two factors - 0.2, 0.4 which are then used to compute a zoom range for all the other Y axes:

// compute the new range based on factor
NRange1DD axisContentRange = axis.ViewRange;
double rangeLength = axisContentRange.End - axisContentRange.Begin;
 

double begin = axisContentRange.Begin + beginFactor * rangeLength;
double end = axisContentRange.Begin + endFactor * rangeLength;


2. Then attach that event handler to the ruler range changed event of the primary y axis:

chart.Axis(StandardAxis.PrimaryY).Scale.RulerRangeChanged += new EventHandler(Scale_RulerRangeChanged);

Hope this helps...

By Jeremy Courbat - Thursday, October 31, 2013

Hi,

Thanks a lot for this amazing reply, I thought something like using the event of the scroll bar, but I given up. Your solution is great but...

(Yes I know! But!)

I translate your code in VB.net and delete the part I didn't need: this is the result:

Private Sub syncChart1YAxisRuler(sender As Object, e As EventArgs)
NChartControl1.Document.Calculate()
'NChartControl1.Document.RecalcLayout(NChartControl1.View.Context)

Dim chart As NChart = NChartControl1.Charts(0)

Dim contentRange As NRange1DD = chart.Axis(StandardAxis.PrimaryY).ViewRange
Dim viewRange As NRange1DD = chart.Axis(StandardAxis.PrimaryY).Scale.RulerRange

' compute factors
Dim beginFactor As Double = contentRange.GetValueFactor(viewRange.Begin)
Dim endFactor As Double = contentRange.GetValueFactor(viewRange.End)

' then for all other y axes make sure their view range factor equals to begin/end factor
For Each axis As NAxis In Chart.Axes
If axis.AxisId <> CInt(StandardAxis.PrimaryY) AndAlso axis.AxisOrientation = AxisOrientation.Vertical Then

' compute the new range based on factor
Dim axisContentRange As NRange1DD = axis.ViewRange
Dim rangeLength As Double = axisContentRange.End - axisContentRange.Begin

Dim begin As Double = axisContentRange.Begin + beginFactor * rangeLength
Dim [end] As Double = axisContentRange.Begin + endFactor * rangeLength

axis.PagingView.ZoomIn(New NRange1DD(begin, [end]), 0.0000001)
End If
Next

NChartControl1.Refresh()
End Sub


When I test the code, my X axis scrollbar range view messed up, so I searched from where it was coming. I didn't know exactly what RecalcLayout do but without this line, it for perfectly.

Thanks a lot.