Search code examples
scichart

Swap scroll bar and X axis labels


I am using trial version of SciChart and doing some tests.

I need to bring scroll bar on top of X axis.

After some research and parsing visual tree, I am planning to change style of SciChartSurface and replace axis and scroll bar, which are placed inside stack panel.

Is this right solution? If AxisAlignment is Top, visual tree may differ. If this is right way to go, where can I find style of surface? Bland does not recognize chart and I can't use it.


Solution

  • I was playing around with this and it is possible to achieve a scrollbar above an XAxis by templating the axis control itself.

    Here is the default control template for the AxisBase control (SciChart v4)

    <ControlTemplate TargetType="axes:AxisBase">
        <Border Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                ap:Device.SnapsToDevicePixels="True">
    
            <StackPanel x:Name="PART_AxisContainer"
                        HorizontalAlignment="Stretch"
                        VerticalAlignment="Stretch"
                        Orientation="{Binding AxisAlignment, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, Converter={StaticResource AxisAlignmentToAxisOrientationConverter}, ConverterParameter=Inverse}"
                        ap:Device.SnapsToDevicePixels="True"
                        apc:AxisLayoutHelper.AxisAlignment="{Binding AxisAlignment, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
    
                <Grid HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch"
                      Canvas.ZIndex="1"
                      ap:Device.SnapsToDevicePixels="True"
                      apc:AxisLayoutHelper.IsInsideItem="True">
    
                    <themes:AxisPanel x:Name="PART_AxisCanvas"
                                      AxisAlignment="{TemplateBinding AxisAlignment}"
                                      Background="Transparent"
                                      DrawLabels="{TemplateBinding DrawLabels}"
                                      DrawMajorTicks="{TemplateBinding DrawMajorTicks}"
                                      DrawMinorTicks="{TemplateBinding DrawMinorTicks}"
                                      IsLabelCullingEnabled="{TemplateBinding IsLabelCullingEnabled}"
                                      MajorTickLineStyle="{TemplateBinding MajorTickLineStyle}"
                                      MinorTickLineStyle="{TemplateBinding MinorTickLineStyle}"
                                      ap:Device.SnapsToDevicePixels="True">
    
                        <Image x:Name="PART_AxisBitmapImage"
                               HorizontalAlignment="Stretch"
                               VerticalAlignment="Stretch"
                               Stretch="Fill"
                               ap:Device.SnapsToDevicePixels="True" />
    
                        <Grid x:Name="PART_LabelsCanvas" Margin="{Binding LabelToTickIndent, RelativeSource={RelativeSource FindAncestor, AncestorType=themes:AxisPanel}, Mode=OneWay}">
                            <themes:TickLabelAxisCanvas AutoFitMarginalLabels="{TemplateBinding AutoFitMarginalLabels}"
                                                        Background="Transparent"
                                                        ClipToBounds="False"
                                                        IsLabelCullingEnabled="{TemplateBinding IsLabelCullingEnabled}"
                                                        ap:Device.SnapsToDevicePixels="True" />
                            <themes:TickLabelAxisCanvas AutoFitMarginalLabels="{TemplateBinding AutoFitMarginalLabels}"
                                                        Background="Transparent"
                                                        ClipToBounds="False"
                                                        IsLabelCullingEnabled="{TemplateBinding IsLabelCullingEnabled}"
                                                        Visibility="Collapsed"
                                                        ap:Device.SnapsToDevicePixels="True" />
                        </Grid>
    
                        <labelProviders:AxisTitle Orientation="{TemplateBinding Orientation}"
                                                  Style="{TemplateBinding TitleStyle}"
                                                  Visibility="{Binding Content, RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseIfNullOrEmptyStringConverter}}" />
                    </themes:AxisPanel>
    
                    <themes:ModifierAxisCanvas x:Name="PART_ModifierAxisCanvas"
                                               HorizontalAlignment="Stretch"
                                               VerticalAlignment="Stretch"
                                               ap:Device.SnapsToDevicePixels="True" />
                </Grid>
    
                <ContentPresenter Content="{TemplateBinding Scrollbar}" apc:AxisLayoutHelper.IsOutsideItem="True" />
            </StackPanel>
        </Border>
    </ControlTemplate>
    

    Here is the modified template (including converters)

    <s:DateTimeAxis AxisAlignment="Bottom"
                AxisTitle="Top Axis"
                BorderThickness="0,0,0,1"
                Id="TopAxisId">
    <s:DateTimeAxis.Resources>
        <s:AxisAlignmentToAxisOrientationConverter x:Key="AxisAlignmentToAxisOrientationConverter" />
        <s:CollapseIfNullOrEmptyStringConverter x:Key="CollapseIfNullOrEmptyStringConverter" />
    </s:DateTimeAxis.Resources>
    <s:DateTimeAxis.Template>
        <ControlTemplate TargetType="s:AxisBase">
            <Border Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            s:Device.SnapsToDevicePixels="True">
    
                <StackPanel x:Name="PART_AxisContainer"
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch"
                    Orientation="{Binding AxisAlignment, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, Converter={StaticResource AxisAlignmentToAxisOrientationConverter}, ConverterParameter=Inverse}"
                    s:Device.SnapsToDevicePixels="True"
                    s:AxisLayoutHelper.AxisAlignment="{Binding AxisAlignment, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
    
                    <ContentPresenter Content="{TemplateBinding Scrollbar}" />
    
                    <Grid HorizontalAlignment="Stretch"
                  VerticalAlignment="Stretch"
                  Canvas.ZIndex="1"
                  s:Device.SnapsToDevicePixels="True"
                  >
    
                        <s:AxisPanel x:Name="PART_AxisCanvas"
                                  AxisAlignment="{TemplateBinding AxisAlignment}"
                                  Background="Transparent"
                                  DrawLabels="{TemplateBinding DrawLabels}"
                                  DrawMajorTicks="{TemplateBinding DrawMajorTicks}"
                                  DrawMinorTicks="{TemplateBinding DrawMinorTicks}"
                                  IsLabelCullingEnabled="{TemplateBinding IsLabelCullingEnabled}"
                                  MajorTickLineStyle="{TemplateBinding MajorTickLineStyle}"
                                  MinorTickLineStyle="{TemplateBinding MinorTickLineStyle}"
                                  s:Device.SnapsToDevicePixels="True">
    
                            <Image x:Name="PART_AxisBitmapImage"
                           HorizontalAlignment="Stretch"
                           VerticalAlignment="Stretch"
                           Stretch="Fill"
                           s:Device.SnapsToDevicePixels="True" />
    
                            <Grid x:Name="PART_LabelsCanvas" Margin="{Binding LabelToTickIndent, RelativeSource={RelativeSource FindAncestor, AncestorType=s:AxisPanel}, Mode=OneWay}">
                                <s:TickLabelAxisCanvas AutoFitMarginalLabels="{TemplateBinding AutoFitMarginalLabels}"
                                                    Background="Transparent"
                                                    ClipToBounds="False"
                                                    IsLabelCullingEnabled="{TemplateBinding IsLabelCullingEnabled}"
                                                    s:Device.SnapsToDevicePixels="True" />
                                <s:TickLabelAxisCanvas AutoFitMarginalLabels="{TemplateBinding AutoFitMarginalLabels}"
                                                    Background="Transparent"
                                                    ClipToBounds="False"
                                                    IsLabelCullingEnabled="{TemplateBinding IsLabelCullingEnabled}"
                                                    Visibility="Collapsed"
                                                    s:Device.SnapsToDevicePixels="True" />
                            </Grid>
    
                            <s:AxisTitle Orientation="{TemplateBinding Orientation}"
                                              Style="{TemplateBinding TitleStyle}"
                                              Visibility="{Binding Content, RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseIfNullOrEmptyStringConverter}}" />
                        </s:AxisPanel>
    
                        <s:ModifierAxisCanvas x:Name="PART_ModifierAxisCanvas"
                                           HorizontalAlignment="Stretch"
                                           VerticalAlignment="Stretch"
                                           s:Device.SnapsToDevicePixels="True" />
                    </Grid>
    
    
                </StackPanel>
            </Border>
        </ControlTemplate>
    </s:DateTimeAxis.Template>
    <s:DateTimeAxis.Scrollbar>
        <s:SciChartScrollbar Margin="0 3 0 0" />
    </s:DateTimeAxis.Scrollbar>
    </s:DateTimeAxis>
    

    This code includes the default control template of the AxisBase in SciChart but removes two critical attached properties: AxisLayoutHelper.IsOutsideItem / IsInsideItem. These properties are used to adjust the order of Axis vs, Scrollbar depending on alignment of the axis. Removing them, you can place the ContentPresenter for the scrollbar anywhere and it will stay put.

    This is tested as working in v4 of SciChart WPF