DEV Community

Cover image for How to add a SciChartOverview or Scrollbar with an ItemsControl of charts, or SciChartGroup
Andrew Bt
Andrew Bt

Posted on • Originally published at scichart.com

How to add a SciChartOverview or Scrollbar with an ItemsControl of charts, or SciChartGroup

A frequently asked question at SciChart is how can I add a SciChartOverview to a Multi-paned Stock Chart hosted by SciChartGroup.

We already have a documented workaround for v2.x or later to add a SciChartOverview to appear under the last chart in an ItemsControl. This works fine for ItemsControls, but it won't work with SciChartGroup.

Below, we present a way to add a Scrollbar to the SciChartGroup (multi-paned stock charts) using the new v3.2 ScrollBar API:

The Problem - Binding to SciChartGroup Templated Items

Why is this so hard? Well the SciChartGroup inherits the WPF ItemsControl. The actual charts are generated by the SciChartGroup.ItemTemplate. There is no reference to these charts at runtime, yet a SciChartOverview needs to bind to a parent surface.

So this code below, isn't going to work:

[xml]
<!-- This won't work ... -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefintion Height="Auto"/>
</Grid.RowDefinitions>

<!-- ItemsControl bound to N Viewmodels, with ItemTemplate showing one chart per view model -->
<!-- Note: SciChartGroup is an ItemsControl so the same problem applies to multi-paned stock charts -->
<ItemsControl Grid.Row="0" ItemsSource="{Binding ChartPaneViewModels}">
<ItemsControl.ItemTemplate>
<s:SciChartSurface x:Name="sciChart">
<!-- Omitted for brevity -->
</s:SciChartSurface>
</ItemsControl.ItemTemplate>
</ItemsControl>

<!-- Requires binding to SciChartSurface, but we can't get this if its inside an ItemTemplate! -->
<sciChart:SciChartOverview Grid.Row="1" ParentSurface="{Binding ElementName=sciChart}"
DataSeries="{Binding ElementName=sciChart, Path=RenderableSeries[1].DataSeries}"
SelectedRange="{Binding ElementName=sciChart, Path=XAxis.VisibleRange, Mode=TwoWay}"/>
[/xml]

This isn't going to work. We must have a reference to first the SciChartSurface created by the ItemsControl. This is what our documented workaround on Adding a SciChartOverview to an ItemsControl does - it digs into the Visual Tree to find the first item generated by the ItemsControl. That's fine for ItemsControls, but it also won't work for SciChartGroup.

The Solution - using SciChartScrollBar (v3.2 or later)

The solution is to use SciChart's new ScrollBar API, part of v3.2 or later.

What we're going to do is include a ScrollBar inside the ItemTemplate for every chart pane, but only show it (Visibility.Visible) for the last chart pane. This gives us full control over the positioning of a scrollbar and ability to customise its background.

Note: this solution will now work with both SciChartGroup (multi-paned stock charts), or, ItemsControls in WPF or Silverlight, in v3.2 of SciChart or later.

The Code

[xml]
<!-- Databinds a SciChartGroup to a list of ChartPaneViewModels -->
<!-- Child chart panes are generated using the ItemTemplate below -->
<s:SciChartGroup Grid.Row="1"
ItemsSource="{Binding ChartPaneViewModels}"
s:ThemeManager.Theme="{Binding ElementName=ThemeCombo, Path=SelectedItem}"
ItemContainerStyle="{StaticResource ChartPaneStyle}">
<s:SciChartGroup.ItemTemplate>
<DataTemplate>

        &lt;!-- DataTemplate instantiates this View per ChartPaneViewModel --&gt;
        &lt;!-- This includes a SciStockChart, which is a specialized form of SciChartSurface --&gt;
        &lt;!-- which is tailored for Stock Charts (financial charts) with CategoryDateTimeAxis --&gt;
        &lt;!--                                                                                 --&gt;
        &lt;!-- It also includes a SciChartScrollbar to create a custom overview control, which is Collapsed for all but the last pane --&gt;

        &lt;Grid&gt;

            &lt;Grid.RowDefinitions&gt;
                &lt;RowDefinition Height=&quot;*&quot;/&gt;
                &lt;RowDefinition Height=&quot;Auto&quot;/&gt;
            &lt;/Grid.RowDefinitions&gt;

            &lt;!-- Databinds each child SciStockChart to ... --&gt;
            &lt;!--  SeriesSource to BaseChartPaneViewModel.ChartSeriesViewModels --&gt;
            &lt;!--  Axis Properties, like s:StockChartXAxis.VisibleRange to CreateMultiPaneStockChartsViewModel.XVisibleRange --&gt;
            &lt;!--  Axis Properties, like s:StockChartYAxis.GrowBy to BaseChartPaneViewModel.IsFirstChartPane with a converter to change behaviour based on pane position--&gt;
            &lt;s:SciStockChart x:Name=&quot;PART_ChartPaneView&quot;
                            SeriesSource=&quot;{Binding ChartSeriesViewModels}&quot;&gt;

                &lt;!-- Properties omitted for brevity --&gt;

            &lt;/s:SciStockChart&gt;

            &lt;!-- Displays a SciChartScrollBar bound to the charts XAxis, and visible only for last chart pane --&gt;
            &lt;Grid Grid.Row=&quot;1&quot; Visibility=&quot;{Binding IsLastChartPane, Converter={StaticResource BoolToVisibilityConverter}}&quot;&gt;

                &lt;!-- This is the Chart behind the scrollbar, bound to the First ChartPaneViewModel, first DataSeries --&gt;
                &lt;!-- It displays the data as a FastMountainRenderableSeries --&gt;
                &lt;s:SciStockChart x:Name=&quot;PART_ScrollbarChartBackground&quot;
                                    Style=&quot;{StaticResource OverviewChartStyle}&quot;&gt;

                    &lt;s:SciStockChart.RenderableSeries&gt;
                        &lt;s:FastMountainRenderableSeries DataSeries=&quot;{Binding ParentViewModel.ChartPaneViewModels[0].ChartSeriesViewModels[0].DataSeries}&quot;/&gt;
                    &lt;/s:SciStockChart.RenderableSeries&gt;

                &lt;/s:SciStockChart&gt;

                &lt;!-- This is the scrollbar, its bound to the PART_ChartPaneView.XAxis above --&gt;
                &lt;s:SciChartScrollbar
                                Margin=&quot;{Binding ElementName=PART_ChartPaneView, Path=Padding, Mode=OneWay}&quot;
                                Axis=&quot;{Binding ElementName=PART_ChartPaneView, Path=XAxis    }&quot;
                                Style=&quot;{StaticResource ScrollBarStyle}&quot;/&gt;
            &lt;/Grid&gt;                        

        &lt;/Grid&gt;
    &lt;/DataTemplate&gt;
&lt;/s:SciChartGroup.ItemTemplate&gt;
Enter fullscreen mode Exit fullscreen mode

</s:SciChartGroup>
[/xml]

Code Walkthrough

  • The SciChartGroup is an ItemsControl. We declare an ItemTemplate to instantiate some view for each ViewModel in the ItemsSource. This is what gives us our multi-paned charts.
  • The ItemTemplate includes a SciStockChart (PART_ChartPaneView) and a scrollbar. So one of each is generated for each ViewModel
  • The Scrollbar area is actually a Grid, and another chart behind it (PART_ScrollBarChartBackground). This is how we create our 'Overview' control.
  • The Grid containing the ScrollBar is only visible for the last chart, see the Visibility binding Visibility="{Binding IsLastChartPane, Converter={StaticResource BoolToVisibilityConverter}}"
  • The overview chart surface (PART_ChartPaneView) must display a MountainSeries from the first chart panes first series. We do this by binding FastMountainRenderableSeries DataSeries="{Binding ParentViewModel.ChartPaneViewModels[0].ChartSeriesViewModels[0].DataSeries}"

How does it look?

Pretty awesome! We will be including this sample with the v3.2 Create Multi-Paned Stock Charts example, which is due to be released very shortly!

SciChartGroup with ScrollBar

Top comments (0)