SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, and now iOS Charting & Android Chart Components

Answered
1
0

Hi All,

I have a situation where the chart needs to be switched between a log scale and a linear scale. To solve this I created 2 axis (one of each) and collapse one of them while the other is visible. The user can switch between them from a context menu.

I declare them in XAML as:

            <s:SciChartSurface.YAxes>
            <s:NumericAxis x:Name="LinearAxis" Id="LinearAxisID" AutoRange="Always" AxisAlignment="Left" AxisTitle="Linear" Style="{StaticResource LinearScaleStyle}" Visibility="Visible" GrowBy="0.0, 0.1"/>
            <s:LogarithmicNumericAxis x:Name="LogAxis"  Id="LogAxisID" AxisAlignment="Left" AxisTitle="Log" Style="{StaticResource LogScaleStyle}" GrowBy="0.0, 0.1" />
        </s:SciChartSurface.YAxes> 

THE ISSUE:
I’ve noticed that the Major and Minor gridlines are drawn based on the order the Axis are declared in <s:SciChartSurface.YAxes> which isn’t a problem. The problem comes when I collapse one axis and make the other visible (obviously re-assigning the series to the visible axis by ID) – The axis and data change as you might expect but the major and minor gridlines are not redrawn.

In summary, if you start with log gridlines, you always get log gridlines – even on a linear axis.

Is there a way to force the redrawing of the gridlines?

  • You must to post comments
Best Answer
0
0

Hi Stuart,

If you want one axis to draw gridlines, and the other not, you need to set AxisBase.IsPrimaryAxis to true (to draw gridlines) or to false (to not draw gridlines). That will solve the problem.

However, I think what you’re looking for is a good way to switch between linear and logarithmic axis. So, here is one way you can do this, with attached behaviours:

SwitchYAxisTypeBehavior

Dynamically Switches an axis instance on a chart depending on a bound boolean property

// Note this could be extended to deal with XAxis quite easily
public class SwitchYAxisTypeBehavior
{
    // Define the Default YAxis -- this can be done in XAML
    public static readonly DependencyProperty DefaultYAxisProperty = DependencyProperty.RegisterAttached(
        "DefaultYAxis", typeof(AxisBase), typeof(SwitchYAxisTypeBehavior), new PropertyMetadata(default(AxisBase), OnPropertyChanged));

    public static void SetDefaultYAxis(DependencyObject element, AxisBase value)
    {
        element.SetValue(DefaultYAxisProperty, value);
    }

    public static AxisBase GetDefaultYAxis(DependencyObject element)
    {
        return (AxisBase)element.GetValue(DefaultYAxisProperty);
    }

    // Define the Alternative YAxis -- this can be done in XAML
    public static readonly DependencyProperty AlternativeYAxisProperty = DependencyProperty.RegisterAttached(
        "AlternativeYAxis", typeof(AxisBase), typeof(SwitchYAxisTypeBehavior), new PropertyMetadata(default(AxisBase), OnPropertyChanged));

    public static void SetAlternativeYAxis(DependencyObject element, AxisBase value)
    {
        element.SetValue(AlternativeYAxisProperty, value);
    }

    public static AxisBase GetAlternativeYAxis(DependencyObject element)
    {
        return (AxisBase)element.GetValue(AlternativeYAxisProperty);
    }

    // Define a boolean attached property which switches between default and alternative YAxis
    public static readonly DependencyProperty UseAlternateYAxisProperty = DependencyProperty.RegisterAttached(
        "UseAlternateYAxis", typeof(bool), typeof(SwitchYAxisTypeBehavior), new PropertyMetadata(default(bool), OnPropertyChanged));

    public static void SetUseAlternateYAxis(DependencyObject element, bool value)
    {
        element.SetValue(UseAlternateYAxisProperty, value);
    }

    public static bool GetUseAlternateYAxis(DependencyObject element)
    {
        return (bool)element.GetValue(UseAlternateYAxisProperty);
    }

    private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // This is where we switch the axis type depending on boolean
        var scs = d as SciChartSurface;
        if (scs == null) return;

        bool useAlternateYAxis = GetUseAlternateYAxis(scs);
        scs.YAxis = useAlternateYAxis ? GetAlternativeYAxis(scs) : GetDefaultYAxis(scs);
    }
}

Usage (XAML):

    <s:SciChartSurface x:Name="sciChart" Grid.Row="1" m:SwitchYAxisTypeBehavior.UseAlternateYAxis="{Binding UseLogarithmicAxis}">

        <m:SwitchYAxisTypeBehavior.DefaultYAxis>
            <s:NumericAxis AxisTitle="Numeric Axis" DrawMajorBands="True" VisibleRange="0, 10" AutoRange="Never"/>
        </m:SwitchYAxisTypeBehavior.DefaultYAxis>

        <m:SwitchYAxisTypeBehavior.AlternativeYAxis>
            <s:LogarithmicNumericAxis AxisTitle="Logarithmic Axis" LogarithmicBase="10" TextFormatting="0.0" CursorTextFormatting="0.0"  
                                      DrawMajorBands="True" VisibleRange="0.1, 10000"/>
        </m:SwitchYAxisTypeBehavior.AlternativeYAxis>

  ...
  </s:SciChartSurface>

Alternatively, if not using MVVM

Attached properties can be set in code as well. The C# equivalent for setting an attached property is:

var scs = new SciChartSurface();
// ... 
SwitchYAxisTypeBehavior.SetDefaultYAxis(scs, new NumericAxis() { ... } );
SwitchYAxisTypeBehavior.SetAlternateYAxis(scs, new LogarithmicNumericAxis() { ... } );
SwitchYAxisTypeBehavior.SetUseAlternateYAxis(scs, true);

Best regards,
Andrew

  • Stuart McCullough
    Hi Andrew - I do like this answer, it solves my immediate problem and points me in the right direction for a proper MVVM implementation. We're trying to move towards this pattern but we're a bit inexperienced and most of the time an expedient solution wins over a proper one. Thanks again
  • Andrew
    If we had time to create answers like this all the time, we would! As our products mature we are hoping to spend more time on educating our users on general WPF tips/tricks as well as scichart API tips. Best regards, Andrew
  • You must to post comments
1
0

I’ve created a better solution than behavior.
I used DataTriggers:

 <Style TargetType="s:SciChartSurface">
    <Setter Property="YAxis" Value="{StaticResource NumericAxisY}" />

    <Style.Triggers>       
        <DataTrigger Binding="{Binding UseLogarithmicAxisY}" Value="True">
            <Setter Property="YAxis" Value="{StaticResource LogarithmicAxisY}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

In my opinion this solution should be in official Examples Suite.

  • Andrew
    It’s a great solution! Thank you for sharing! Please be advised – if you share the LogarithmicAxisY instance on more than one chart, it will break. Ensure the LogarithmicAxisY is declared with x:Shared=”False” to prevent this
  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.