I want change the MajorTickMode that is used by an axis if data are zoomed along that axis and then restore the axis' MajorTickMode if data are un-zoomed along that axis.
I need help finding a way to set Axis.ScaleConfigurator.MajorTickMode after data are zoomed by the user (via the NDataZoomTool) and have the changes take effect before the chart is refreshed. If I change Axis.ScaleConfigurator.MajorTickMode after handling the axis' RulerRangeChanged event then the new MajorTickMode doesn't seem to take effect until the second time that the chart is refreshed after the MajorTickMode is changed.
The behavior of ScrollBar visibility is a good example of the behavior that I'm looking for. I can't use ScrollBars because I always set Chart.Enable3D = True, but the idea is that if ScrollBars would be visible then I want to use MajorTickMode = AutoMinDistance and if ScrollBars would not be visible then I want to use MajorTickMode = CustomStep.
Please see the following example. Note that MajorTickMode of the Y axes is set in the UpdateTickMode method. ChartControl.Refresh is always called after UpdateTickMode is called, but changes to MajorTickMode don't seem to take effect until the second time the chart is refreshed (e.g., if the form's size is changed or the user right clicks on the chart in order to interact with the chart via the NDataPanTool). Also note that the form's Text shows the current values of the MajorTickMode property for the Y axes.
Public Class ChangeTickModeAfterDataZoomForm
Inherits System.Windows.Forms.Form
Protected _ChartControl As Nevron.Chart.WinForm.NChartControl
Private components As System.ComponentModel.Container = Nothing
Public Sub New()
InitializeComponent()
End Sub
''' <summary>
''' Clean up any resources being used.
''' </summary>
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not components Is Nothing Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
#Region "Component Designer generated code"
''' <summary>
''' Required method for Designer support - do not modify
''' the contents of this method with the code editor.
''' </summary>
Private Sub InitializeComponent()
Me.SuspendLayout()
'
' ChangeTickModeAfterDataZoomForm
'
Me.Name = "ChangeTickModeAfterDataZoomForm"
Me.Size = New System.Drawing.Size(1000, 800)
Me.ResumeLayout(False)
Me.StartPosition = FormStartPosition.CenterScreen
Call Me.Initialize()
End Sub
#End Region
Public Overridable Sub Initialize()
Me._ChartControl = New Nevron.Chart.WinForm.NChartControl
Me._ChartControl.Dock = DockStyle.Fill
'Me._ChartControl.Settings.ShapeRenderingMode = Nevron.GraphicsCore.ShapeRenderingMode.Default
Me._ChartControl.Settings.JitterMode = Nevron.Chart.JitterMode.Disabled
'Me._ChartControl.Settings.AutoJitterInterval = 2000
Me._ChartControl.Settings.RenderSurface = Nevron.GraphicsCore.RenderSurface.Window
Me.Controls.Add(Me._ChartControl)
' set a chart title
Dim title As Nevron.Chart.NLabel = Me._ChartControl.Labels.AddHeader("Multiple Axes Zooming and Scrolling")
title.TextStyle.FontStyle = New Nevron.GraphicsCore.NFontStyle("Times New Roman", 18, Drawing.FontStyle.Italic)
title.ContentAlignment = Drawing.ContentAlignment.BottomCenter
title.Location = New Nevron.GraphicsCore.NPointL(New Nevron.GraphicsCore.NLength(50, Nevron.GraphicsCore.NRelativeUnit.ParentPercentage), New Nevron.GraphicsCore.NLength(2, Nevron.GraphicsCore.NRelativeUnit.ParentPercentage))
' configure chart
Dim chart As Nevron.Chart.NCartesianChart = CType(Me._ChartControl.Charts(0), Nevron.Chart.NCartesianChart)
'
chart.Enable3D = True
chart.Projection.SetPredefinedProjection(Nevron.GraphicsCore.PredefinedProjection.Orthogonal)
'
chart.RangeSelections.Add(New Nevron.Chart.NRangeSelection())
' 2D line chart
chart.BoundsMode = Nevron.GraphicsCore.BoundsMode.Stretch
' configure axis paging and set a mimimum range length on the axisthis will prevent the user from zooming too much
chart.Axis(Nevron.Chart.StandardAxis.PrimaryX).ScrollBar.Visible = True
Dim palette As Nevron.Chart.NChartPalette = New Nevron.Chart.NChartPalette(Nevron.Chart.ChartPredefinedPalette.Fresh)
Dim color1 As Drawing.Color = palette.SeriesColors(0)
Dim color2 As Drawing.Color = palette.SeriesColors(3)
Dim primaryY As Nevron.Chart.NAxis = chart.Axis(Nevron.Chart.StandardAxis.PrimaryY)
primaryY.ScaleConfigurator.Title.Text = "Primary Y Axis"
ApplyColorToAxis(primaryY, color1)
primaryY.ScrollBar.Visible = True
AddHandler primaryY.Scale.RulerRangeChanged, AddressOf Scale_RulerRangeChanged
Dim secondaryY As Nevron.Chart.NAxis = chart.Axis(Nevron.Chart.StandardAxis.SecondaryY)
secondaryY.ScaleConfigurator.Title.Text = "Secondary Y Axis"
ApplyColorToAxis(secondaryY, color2)
secondaryY.Visible = True
Dim line1 As Nevron.Chart.NLineSeries = New Nevron.Chart.NLineSeries()
line1.BorderStyle.Color = color1
line1.BorderStyle.Width = New Nevron.GraphicsCore.NLength(2)
chart.Series.Add(line1)
line1.DataLabelStyle.Visible = False
Dim line2 As Nevron.Chart.NLineSeries = New Nevron.Chart.NLineSeries()
line2.BorderStyle.Color = color2
line2.BorderStyle.Width = New Nevron.GraphicsCore.NLength(2)
chart.Series.Add(line2)
line2.DataLabelStyle.Visible = False
line2.DisplayOnAxis(Nevron.Chart.StandardAxis.PrimaryY, False)
line2.DisplayOnAxis(Nevron.Chart.StandardAxis.SecondaryY, True)
For i As Integer = 0 To 719
Const degree2Rad As Double = Math.PI / 180.0#
Dim angle As Double = i * degree2Rad
Dim value1 As Double = Math.Sin(angle)
Dim value2 As Double = Math.Sin(4.0# * angle + 40) * 50 + 1234
line1.Values.Add(value1)
line2.Values.Add(value2)
Next i
Me._ChartControl.Controller.Tools.Add(New Nevron.Chart.Windows.NSelectorTool())
Me._ChartControl.Controller.Tools.Add(New Nevron.Chart.Windows.NAxisScrollTool())
Me._ChartControl.Controller.Tools.Add(New Nevron.Chart.Windows.NDataZoomTool())
Me._ChartControl.Controller.Tools.Add(New Nevron.Chart.Windows.NDataPanTool())
Call Me.UpdateTickMode()
Me._ChartControl.Refresh()
End Sub
Private Sub ApplyColorToAxis(ByVal axis As Nevron.Chart.NAxis, ByVal color As Drawing.Color)
Dim scale As Nevron.Chart.NLinearScaleConfigurator = CType(axis.ScaleConfigurator, Nevron.Chart.NLinearScaleConfigurator)
scale.InnerMajorTickStyle.LineStyle.Color = color
scale.InnerMinorTickStyle.LineStyle.Color = color
scale.OuterMajorTickStyle.LineStyle.Color = color
scale.OuterMinorTickStyle.LineStyle.Color = color
scale.LabelStyle.TextStyle.FillStyle = New Nevron.GraphicsCore.NColorFillStyle(color)
scale.Title.TextStyle.FillStyle = New Nevron.GraphicsCore.NColorFillStyle(color)
scale.RulerStyle.BorderStyle.Color = color
End Sub
Private Sub Scale_RulerRangeChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim chart As Nevron.Chart.NChart = Me._ChartControl.Charts(0)
Dim contentRange As Nevron.GraphicsCore.NRange1DD = chart.Axis(Nevron.Chart.StandardAxis.PrimaryY).ContentRange
Dim viewRange As Nevron.GraphicsCore.NRange1DD = chart.Axis(Nevron.Chart.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
If beginFactor = 0.0 AndAlso endFactor = 1.0 Then
' disable zoom
For Each axis As Nevron.Chart.NAxis In chart.Axes
If axis.AxisId <> CInt(Nevron.Chart.StandardAxis.PrimaryY) AndAlso axis.AxisOrientation = Nevron.Chart.AxisOrientation.Vertical Then
axis.PagingView.Enabled = False
End If
Next axis
Else
' disable zoom
For Each axis As Nevron.Chart.NAxis In chart.Axes
If (axis.AxisId <> CInt(Nevron.Chart.StandardAxis.PrimaryY)) AndAlso (axis.AxisOrientation = Nevron.Chart.AxisOrientation.Vertical) Then
axis.PagingView.Enabled = True
' compute the new range based on factor
Dim axisContentRange As Nevron.GraphicsCore.NRange1DD = axis.ContentRange
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 Nevron.GraphicsCore.NRange1DD(begin, [end]), 0.0001)
End If
Next axis
End If
Call Me.UpdateTickMode()
Me._ChartControl.Refresh()
End Sub
Private Sub UpdateTickMode()
Dim chart As Nevron.Chart.NCartesianChart = CType(Me._ChartControl.Charts(0), Nevron.Chart.NCartesianChart)
Dim axis As Nevron.Chart.NAxis
Dim scaleConfigurator As Nevron.Chart.NNumericScaleConfigurator
Dim tickModePrimaryY As Nevron.Chart.MajorTickMode
Dim tickModeSecondaryY As Nevron.Chart.MajorTickMode
axis = chart.Axis(Nevron.Chart.StandardAxis.PrimaryY)
scaleConfigurator = DirectCast(axis.ScaleConfigurator, Nevron.Chart.NNumericScaleConfigurator)
scaleConfigurator.CustomStep = 0.5
scaleConfigurator.MajorTickMode = GetTickMode(axis)
tickModePrimaryY = scaleConfigurator.MajorTickMode
axis = chart.Axis(Nevron.Chart.StandardAxis.SecondaryY)
scaleConfigurator = DirectCast(axis.ScaleConfigurator, Nevron.Chart.NNumericScaleConfigurator)
scaleConfigurator.CustomStep = 25
scaleConfigurator.MajorTickMode = GetTickMode(axis)
tickModeSecondaryY = scaleConfigurator.MajorTickMode
Static cnt As Integer : cnt += 1
Dim message As String = System.String.Format("{0} UpdateTickMode: PrimaryY={1}, SecondaryY={2}", cnt.ToString("000"), tickModePrimaryY, tickModeSecondaryY)
Me.Text = message
End Sub
Private Function GetTickMode(ByVal axis As Nevron.Chart.NAxis) As Nevron.Chart.MajorTickMode
If (axis.PagingView.Enabled) Then
Return Nevron.Chart.MajorTickMode.AutoMinDistance
Else
Return Nevron.Chart.MajorTickMode.CustomStep
End If
End Function
End Class