SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, iOS Chart, Android Chart and JavaScript Chart Components
SciChart WPF ships with hundreds of WPF Chart Examples which you can browse, play with, view the source-code and even export each WPF Chart Example to a stand-alone Visual Studio solution. All of this is possible with the new and improved SciChart WPF Examples Suite, which ships as part of the SciChart WPF SDK.
The Discontinuous Axis Demo shows how to use a new Axis type – the DiscontinuousDateTimeAxis – which is a DateTime Value Axis (measures X-position by X-value) that allows collapsing of gaps in the data.
For example, a DiscontinuousDateTimeAxis and a dataset of trading data (futures, forex or stocks), the DiscontinuousDateTimeAxis can be used to show or hide weekend or overnight gaps in data.
A calendar is applied to the DiscontinuousDateTimeAxis which contains the times to skip. Special days such as holidays or weekends can also be skipped.
Finally, the DiscontinuousDateTimeAxis may be used in process control systems, which require a DateTimeAxis but removing of certain times or date ranges from the axis.
Documentation Links
– FastCandlestickRenderableSeries Type
– The DiscontinuousDateTimeAxis
The C#/WPF source code for the WPF Chart Discontinuous Axis Demo example is included below (Scroll down!).
Did you know you can also view the source code from one of the following sources as well?
<UserControl x:Class="SciChart.Examples.Examples.SeeFeaturedApplication.DiscontinuousAxisDemo.DiscontinuousAxisView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ext="http://schemas.abtsoftware.co.uk/scichart/exampleExternals"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
xmlns:local="clr-namespace:SciChart.Examples.Examples.SeeFeaturedApplication.DiscontinuousAxisDemo"
d:DataContext="{d:DesignInstance local:DiscontinuousAxisViewModel, IsDesignTimeCreatable=True}"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/SciChart.Examples.ExternalDependencies;component/Resources/Styles/MergedResources.xaml" />
<ResourceDictionary Source="/SciChart.Examples.ExternalDependencies;component/Resources/Styles/ToolbarButtonsCommon.xaml" />
</ResourceDictionary.MergedDictionaries>
<s:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<s:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<ext:IsChartTypeConverter x:Key="IsChartTypeConverter" />
<ext:IsSameObjectsMultiConverter x:Key="IsSameSeriesMultiConverter"/>
<ext:EnumValueToStringConverter x:Key="SelectedEnumValueConverter"/>
<Style x:Key="DataItemTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{Binding Stroke, Converter={StaticResource ColorToBrushConverter}}"/>
<Setter Property="MinWidth" Value="80"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="Margin" Value="0,0,20,0"/>
</Style>
<!-- DataTemplate for the SeriesInfo which are exposed on the RolloverModifier -->
<DataTemplate x:Key="ChartDataTemplate" DataType="s:SeriesInfo">
<TextBlock Style="{StaticResource DataItemTextBlockStyle}">
<Run Text="{Binding SeriesName, StringFormat=\{0\}:}"/>
<Run Text="{Binding Value, StringFormat=\{0:0.000\}}"/>
</TextBlock>
</DataTemplate>
<!-- Style for the 50-period Moving Average -->
<Style x:Key="Ma50SeriesStyle" TargetType="s:FastLineRenderableSeries">
<Setter Property="ResamplingMode" Value="MinMax" />
<Setter Property="Stroke" Value="#FFE13219" />
<Setter Property="StrokeThickness" Value="2" />
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#AAE13219"
Stroke="White"
StrokeThickness="2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for 200 period Moving Average -->
<Style x:Key="Ma200SeriesStyle" TargetType="s:FastLineRenderableSeries">
<Setter Property="ResamplingMode" Value="MinMax" />
<Setter Property="Stroke" Value="#FFFFA500" />
<Setter Property="StrokeThickness" Value="2" />
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#AAFFA500"
Stroke="White"
StrokeThickness="2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for the Price line chart -->
<Style x:Key="PriceLineSeriesStyle" TargetType="s:FastLineRenderableSeries">
<Setter Property="ResamplingMode" Value="MinMax" />
<Setter Property="Stroke" Value="#FF4083B7" />
<Setter Property="StrokeThickness" Value="2" />
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#FF4083B7"
Stroke="White"
StrokeThickness="2" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="IsVisible" Value="{Binding SelectedChartType, Mode=TwoWay, Converter={StaticResource IsChartTypeConverter}, ConverterParameter=FastLine}" />
</Style>
<!-- Style for the Price mountain chart -->
<Style x:Key="PriceMountainSeriesStyle" TargetType="s:FastMountainRenderableSeries">
<Setter Property="ResamplingMode" Value="MinMax" />
<Setter Property="Stroke" Value="#FFC6E6FF" />
<Setter Property="Fill" Value="#774083B7" />
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#774083B7"
Stroke="White"
StrokeThickness="2" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="IsVisible" Value="{Binding SelectedChartType, Mode=TwoWay, Converter={StaticResource IsChartTypeConverter}, ConverterParameter=FastMountain}" />
</Style>
<!-- Style for the Price Column chart -->
<Style x:Key="PriceColumnSeriesStyle" TargetType="s:FastColumnRenderableSeries">
<Setter Property="ResamplingMode" Value="MinMax" />
<Setter Property="Stroke" Value="#FFC6E6FF" />
<Setter Property="Fill">
<Setter.Value>
<SolidColorBrush Color="#774083B7" />
</Setter.Value>
</Setter>
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#774083B7"
Stroke="White"
StrokeThickness="2" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="IsVisible" Value="{Binding SelectedChartType, Mode=TwoWay, Converter={StaticResource IsChartTypeConverter}, ConverterParameter=FastColumn}" />
</Style>
<!-- Style for Candlestick chart -->
<Style x:Key="PriceCandlestickSeriesStyle" TargetType="s:FastCandlestickRenderableSeries">
<Setter Property="IsVisible" Value="{Binding SelectedChartType, Mode=TwoWay, Converter={StaticResource IsChartTypeConverter}, ConverterParameter=FastCandlestick}" />
<Setter Property="ResamplingMode" Value="MinMax" />
<Setter Property="StrokeUp" Value="#FF52CC54" />
<Setter Property="StrokeDown" Value="#FFE26565" />
<Setter Property="FillUp">
<Setter.Value>
<SolidColorBrush Color="#7052CC54" />
</Setter.Value>
</Setter>
<Setter Property="FillDown">
<Setter.Value>
<SolidColorBrush Color="#D0E26565" />
</Setter.Value>
</Setter>
<Setter Property="AntiAliasing" Value="False" />
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#FF52CC54"
Stroke="White"
StrokeThickness="2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for Ohlc chart -->
<Style x:Key="PriceOhlcSeriesStyle" TargetType="s:FastOhlcRenderableSeries">
<Setter Property="IsVisible" Value="{Binding SelectedChartType, Mode=TwoWay, Converter={StaticResource IsChartTypeConverter}, ConverterParameter=FastOhlc}" />
<Setter Property="ResamplingMode" Value="MinMax" />
<Setter Property="StrokeUp" Value="#FF52CC54" />
<Setter Property="StrokeDown" Value="#FFE26565" />
<Setter Property="AntiAliasing" Value="False" />
<Setter Property="RolloverMarkerTemplate">
<Setter.Value>
<ControlTemplate>
<Ellipse Width="9"
Height="9"
Fill="#FF52CC54"
Stroke="White"
StrokeThickness="2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Define the Toolbar -->
<Border Panel.ZIndex="9999"
Background="#FF232426"
BorderBrush="#323539"
BorderThickness="0,0,2,0">
<WrapPanel HorizontalAlignment="Left" Orientation="Vertical">
<ToggleButton Content="Zoom"
HorizontalAlignment="Left"
Command="{Binding SetRubberBandModifierCommand}"
IsChecked="{Binding IsRubberBandZoomSelected, Mode=OneWay}"
Style="{StaticResource ZoomButtonStyle}"
ToolTipService.ToolTip="Toggle Rubber-Band Zoom"/>
<ext:FlyoutMenuToggleButton Content="Pan"
HorizontalAlignment="Left"
Command="{Binding SetZoomPanModifierCommand}"
IsChecked="{Binding IsZoomPanSelected, Mode=OneWay}"
Style="{StaticResource PanToggleButtonStyle}"
ToolTipService.ToolTip="Toggle Zoom-Pan">
<ext:FlyoutMenuToggleButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<TextBlock Text="Direction"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:XyDirection}}}"
SelectedItem="{Binding Source={x:Reference Name=ZoomPanMod}, Path=XyDirection, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
</StackPanel>
</ext:FlyoutMenuToggleButton.PopupContent>
</ext:FlyoutMenuToggleButton>
<ext:FlyoutSeparator/>
<Button Content="Zoom Extents"
HorizontalAlignment="Left"
Command="{Binding Source={x:Reference Name=PriceChart}, Path=AnimateZoomExtentsCommand}"
Style="{StaticResource ZoomExtentsButtonStyle}"
ToolTipService.ToolTip="Zoom to Extents"/>
<ext:FlyoutMenuButton Content="Wheel"
HorizontalAlignment="Left"
Style="{StaticResource MouseWheelButtonStyle}"
ToolTipService.ToolTip="MouseWheel">
<ext:FlyoutMenuButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<TextBlock Text="Action Type"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:ActionType}}}"
SelectedItem="{Binding ActionType, Source={x:Reference Name=MouseWheelZoomMod}, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<TextBlock Text="Direction"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:XyDirection}}}"
SelectedItem="{Binding XyDirection, Source={x:Reference Name=MouseWheelZoomMod}, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
</StackPanel>
</ext:FlyoutMenuButton.PopupContent>
</ext:FlyoutMenuButton>
<!-- Rollover modifier -->
<ext:FlyoutMenuToggleButton HorizontalAlignment="Left"
HorizontalContentAlignment="Center"
Command="{Binding SetRolloverModifierCommand}"
Content="ROLL"
FontSize="10"
IsChecked="{Binding IsRolloverSelected, Mode=OneWay}"
Padding="0"
Style="{StaticResource FlyoutMenuToggleButtonStyle}"
ToolTipService.ToolTip="Rollover">
<ext:FlyoutMenuToggleButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<TextBlock FontSize="12" Text="Rollover mode"/>
<ComboBox FontSize="12"
ItemsSource="{Binding Source={ext:EnumValues {x:Type s:SourceMode}}}"
SelectedItem="{Binding SourceMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<TextBlock FontSize="12" Text="Show tooltip mode"/>
<ComboBox FontSize="12"
ItemsSource="{Binding Source={ext:EnumValues {x:Type s:ShowTooltipOptions}}}"
SelectedItem="{Binding ShowTooltipMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<CheckBox Margin="3"
VerticalAlignment="Center"
Content="Show axis label"
FontSize="12"
IsChecked="{Binding ShowAxisLabels, Mode=TwoWay}"/>
</StackPanel>
</ext:FlyoutMenuToggleButton.PopupContent>
</ext:FlyoutMenuToggleButton>
<!-- Cursor modifier -->
<ext:FlyoutMenuToggleButton HorizontalAlignment="Left"
HorizontalContentAlignment="Center"
Command="{Binding SetCursorModifierCommand}"
Content="CUR"
IsChecked="{Binding IsCursorSelected, Mode=OneWay}"
Padding="0"
Style="{StaticResource CursorButtonStyle}">
<ext:FlyoutMenuToggleButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<StackPanel.Resources>
<ext:SnappingModeToVisibilityConverter x:Key="SnappingModeToVisibilityConverter"/>
</StackPanel.Resources>
<TextBlock Text="Cursor mode"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:SourceMode}}}"
SelectedItem="{Binding SourceMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<TextBlock Text="Show tooltip mode"/>
<ComboBox ItemsSource="{Binding Source={ext:EnumValues {x:Type s:ShowTooltipOptions}}}"
SelectedItem="{Binding ShowTooltipMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<TextBlock Text="Snapping mode"/>
<ComboBox x:Name="snappingModeCmbx"
ItemsSource="{Binding Source={ext:EnumValues {x:Type s:CursorSnappingMode}}}"
SelectedItem="{Binding Source={x:Reference Name=CursorMod}, Path=SnappingMode, Mode=TwoWay, Converter={StaticResource SelectedEnumValueConverter}}"/>
<ext:FlyoutSeparator/>
<StackPanel Orientation="Vertical" Visibility="{Binding SelectedItem, Source={x:Reference Name=snappingModeCmbx}, Mode=OneWay, Converter={StaticResource SnappingModeToVisibilityConverter}}">
<TextBlock Text="Snap to"/>
<ComboBox FontSize="12"
ItemsSource="{Binding AllSeriesNames, Mode=OneWay}"
SelectedItem="{Binding SelectedSeriesToSnap, Mode=TwoWay}"/>
<ext:FlyoutSeparator/>
</StackPanel>
<CheckBox Margin="3"
VerticalAlignment="Center"
Content="Show axis label"
IsChecked="{Binding ShowAxisLabels, Mode=TwoWay}"/>
</StackPanel>
</ext:FlyoutMenuToggleButton.PopupContent>
</ext:FlyoutMenuToggleButton>
<ext:FlyoutSeparator/>
<ext:FlyoutMenuButton x:Name="traderDataExample"
HorizontalAlignment="Left"
Content="Data"
FontSize="11"
Padding="0"
Style="{StaticResource FlyoutMenuButtonStyle}"
ToolTipService.ToolTip="Data">
<ext:FlyoutMenuButton.PopupContent>
<StackPanel MinWidth="150" Orientation="Vertical">
<TextBlock FontSize="12" Text="Chart Type:"/>
<ComboBox Margin="2"
FontSize="12"
ItemsSource="{Binding AllChartTypes}"
SelectedItem="{Binding SelectedChartType, Mode=TwoWay}"/>
<ext:FlyoutSeparator />
<TextBlock FontSize="12" Text="Calendar:"/>
<ComboBox Margin="2"
FontSize="12"
ItemsSource="{Binding AllCalendars}"
SelectedItem="{Binding SelectedCalendar, Mode=TwoWay}"/>
</StackPanel>
</ext:FlyoutMenuButton.PopupContent>
</ext:FlyoutMenuButton>
</WrapPanel>
</Border>
<Grid Grid.Column="1" Background="#333">
<s:SciChartSurface x:Name="PriceChart" Annotations="{Binding Annotations}">
<s:SciChartSurface.RenderableSeries>
<!-- Series 0..4 are shown or hidden based on ChartType property in ViewModel bound to IsVisible on series -->
<!-- Only one is shown at any one time and these series show the data for DataSet.Series[0] -->
<s:FastCandlestickRenderableSeries DataSeries="{Binding PriceSeries}" Style="{StaticResource PriceCandlestickSeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastCandlestickRenderableSeries>
<s:FastOhlcRenderableSeries DataSeries="{Binding PriceSeries}" Style="{StaticResource PriceOhlcSeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastOhlcRenderableSeries>
<s:FastMountainRenderableSeries DataSeries="{Binding PriceSeries}" Style="{StaticResource PriceMountainSeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastMountainRenderableSeries>
<s:FastLineRenderableSeries DataSeries="{Binding PriceSeries}" Style="{StaticResource PriceLineSeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastLineRenderableSeries>
<s:FastColumnRenderableSeries DataSeries="{Binding PriceSeries}" Style="{StaticResource PriceColumnSeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastColumnRenderableSeries>
<!-- Series 5, 6 are always visible -->
<s:FastLineRenderableSeries DataSeries="{Binding Sma50Series}" Style="{StaticResource Ma50SeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastLineRenderableSeries>
<s:FastLineRenderableSeries DataSeries="{Binding Sma200Series}" Style="{StaticResource Ma200SeriesStyle}">
<s:CursorModifier.SnapToSeries>
<MultiBinding Converter="{StaticResource IsSameSeriesMultiConverter}" Mode="OneWay">
<Binding Path="DataSeries.SeriesName" RelativeSource="{RelativeSource Self}"/>
<Binding Path="SelectedSeriesToSnap"/>
</MultiBinding>
</s:CursorModifier.SnapToSeries>
</s:FastLineRenderableSeries>
</s:SciChartSurface.RenderableSeries>
<!-- Create X Axis. Optional bands give a cool look and feel for minimal performance impact -->
<s:SciChartSurface.XAxis>
<s:DiscontinuousDateTimeAxis Calendar="{Binding Calendar, Mode=TwoWay}"
DrawMajorBands="True"
GrowBy="0.0, 0.1" />
</s:SciChartSurface.XAxis>
<!-- Create Y Axis -->
<s:SciChartSurface.YAxis>
<s:NumericAxis AutoRange="Always"
GrowBy="0.1, 0.1" />
</s:SciChartSurface.YAxis>
<!-- Create and enable ChartModifiers through bindings -->
<s:SciChartSurface.ChartModifier>
<s:ModifierGroup>
<s:RolloverModifier x:Name="RolloverMod"
IsEnabled="{Binding IsRolloverSelected, Mode=OneWay}"
ReceiveHandledEvents="True"
ShowAxisLabels="{Binding ShowAxisLabels}"
ShowTooltipOn="{Binding ShowTooltipMode}"
SourceMode="{Binding SourceMode}"/>
<s:CursorModifier x:Name="CursorMod"
IsEnabled="{Binding IsCursorSelected, Mode=OneWay}"
ReceiveHandledEvents="True"
ShowAxisLabels="{Binding ShowAxisLabels}"
ShowTooltip="True"
ShowTooltipOn="{Binding ShowTooltipMode}"
SourceMode="{Binding SourceMode}"/>
<s:MouseWheelZoomModifier x:Name="MouseWheelZoomMod"
ReceiveHandledEvents="True"
XyDirection="XYDirection"
ActionType="Zoom"/>
<s:RubberBandXyZoomModifier IsEnabled="{Binding IsRubberBandZoomSelected, Mode=OneWay}"
ReceiveHandledEvents="True"
IsXAxisOnly="True"/>
<s:ZoomPanModifier x:Name="ZoomPanMod"
ClipModeX="None"
IsEnabled="{Binding IsZoomPanSelected, Mode=OneWay}"
ReceiveHandledEvents="True"/>
<s:ZoomExtentsModifier ExecuteOn="MouseDoubleClick"/>
</s:ModifierGroup>
</s:SciChartSurface.ChartModifier>
</s:SciChartSurface>
<ItemsControl Margin="20"
IsHitTestVisible="False"
VerticalAlignment="Top"
DataContext="{Binding Source={x:Reference Name=PriceChart}, Path=ChartModifier}"
ItemTemplate="{StaticResource ChartDataTemplate}"
ItemsSource="{Binding Path=[RolloverModifier].SeriesData.SeriesInfo}"
Visibility="{Binding Path=[RolloverModifier].IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</Grid>
</UserControl>
// *************************************************************************************
// SCICHART® Copyright SciChart Ltd. 2011-2022. All rights reserved.
//
// Web: http://www.scichart.com
// Support: support@scichart.com
// Sales: sales@scichart.com
//
// DiscontinuousAxisView.xaml.cs is part of the SCICHART® Examples. Permission is hereby granted
// to modify, create derivative works, distribute and publish any part of this source
// code whether for commercial, private or personal use.
//
// The SCICHART® examples are distributed in the hope that they will be useful, but
// without any warranty. It is provided "AS IS" without warranty of any kind, either
// expressed or implied.
// *************************************************************************************
namespace SciChart.Examples.Examples.SeeFeaturedApplication.DiscontinuousAxisDemo
{
public partial class DiscontinuousAxisView
{
public DiscontinuousAxisView()
{
InitializeComponent();
}
}
}
// *************************************************************************************
// SCICHART Copyright SciChart Ltd. 2011-2022. All rights reserved.
//
// Web: http://www.scichart.com
// Support: support@scichart.com
// Sales: sales@scichart.com
//
// DiscontinuousAxisViewModel.cs is part of the SCICHART Examples. Permission is hereby granted
// to modify, create derivative works, distribute and publish any part of this source
// code whether for commercial, private or personal use.
//
// The SCICHART examples are distributed in the hope that they will be useful, but
// without any warranty. It is provided "AS IS" without warranty of any kind, either
// expressed or implied.
// *************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using SciChart.Charting.ChartModifiers;
using SciChart.Charting.Common.Helpers;
using SciChart.Charting.Model.DataSeries;
using SciChart.Charting.Model.Filters;
using SciChart.Charting.Numerics.Calendars;
using SciChart.Charting.Visuals.Annotations;
using SciChart.Examples.Examples.AnnotateAChart.OverlayTradeMarkers;
using SciChart.Examples.Examples.SeeFeaturedApplication.Common;
using SciChart.Examples.ExternalDependencies.Common;
using SciChart.Examples.ExternalDependencies.Data;
namespace SciChart.Examples.Examples.SeeFeaturedApplication.DiscontinuousAxisDemo
{
public class DiscontinuousAxisViewModel : BaseViewModel
{
private readonly IOhlcDataSeries<DateTime, double> _priceData = new OhlcDataSeries<DateTime, double>();
private IOhlcDataSeries<DateTime, double> _priceSeries;
private IXyDataSeries<DateTime, double> _sma200Series;
private IXyDataSeries<DateTime, double> _sma50Series;
private ModifierType _chartZoomModifier;
private ModifierType _chartSeriesModifier;
private ChartType _chartType;
private ShowTooltipOptions _showTooltipMode;
private SourceMode _sourceMode;
private bool _showAxisLabels;
private string _selectedCalendar;
private string _selectedSeriesToSnap;
private IDiscontinuousDateTimeCalendar _calendar;
private AnnotationCollection _annotations;
public DiscontinuousAxisViewModel()
{
var priceSeries = DataManager.Instance.GetPriceData("EURUSD", TimeFrame.Minute5);
_priceData.Append(priceSeries.TimeData, priceSeries.OpenData, priceSeries.HighData, priceSeries.LowData, priceSeries.CloseData);
SetZoomPanModifierCommand = new ActionCommand(() => ChartZoomModifier = IsZoomPanSelected ? ModifierType.Null : ModifierType.ZoomPan);
SetRubberBandModifierCommand = new ActionCommand(() => ChartZoomModifier = IsRubberBandZoomSelected ? ModifierType.Null : ModifierType.RubberBandZoom);
SetCursorModifierCommand = new ActionCommand(() => ChartSeriesModifier = IsCursorSelected ? ModifierType.Null : ModifierType.CrosshairsCursor);
SetRolloverModifierCommand = new ActionCommand(() => ChartSeriesModifier = IsRolloverSelected ? ModifierType.Null : ModifierType.Rollover);
Annotations = CreateAnnotations();
SetDefaults();
InitializeChartSurface();
}
public ActionCommand SetZoomPanModifierCommand { get; }
public ActionCommand SetRubberBandModifierCommand { get; }
public ActionCommand SetCursorModifierCommand { get; }
public ActionCommand SetRolloverModifierCommand { get; }
public bool IsZoomPanSelected => ChartZoomModifier == ModifierType.ZoomPan;
public bool IsRubberBandZoomSelected => ChartZoomModifier == ModifierType.RubberBandZoom;
public bool IsCursorSelected => ChartSeriesModifier == ModifierType.CrosshairsCursor;
public bool IsRolloverSelected => ChartSeriesModifier == ModifierType.Rollover;
public IEnumerable<string> AllSeriesNames { get; } = new[] { "PriceData", "200 SMA", "50 SMA" };
public IEnumerable<ChartType> AllChartTypes { get; } = new[]
{
ChartType.FastLine,
ChartType.FastColumn,
ChartType.FastMountain,
ChartType.FastCandlestick,
ChartType.FastOhlc
};
public IEnumerable<string> AllCalendars { get; } = new[]
{
"Extended",
"NYSE",
"LSE"
};
public IOhlcDataSeries<DateTime, double> PriceSeries
{
get => _priceSeries;
set
{
_priceSeries = value;
_priceSeries.SeriesName = "PriceData";
OnPropertyChanged(nameof(PriceSeries));
}
}
public IXyDataSeries<DateTime, double> Sma200Series
{
get => _sma200Series;
set
{
_sma200Series = value;
_sma200Series.SeriesName = "200 SMA";
OnPropertyChanged(nameof(Sma200Series));
}
}
public IXyDataSeries<DateTime, double> Sma50Series
{
get => _sma50Series;
set
{
_sma50Series = value;
_sma50Series.SeriesName = "50 SMA";
OnPropertyChanged(nameof(Sma50Series));
}
}
public ChartType SelectedChartType
{
get => _chartType;
set
{
_chartType = value;
OnPropertyChanged(nameof(SelectedChartType));
}
}
public string SelectedSeriesToSnap
{
get => _selectedSeriesToSnap;
set
{
_selectedSeriesToSnap = value;
OnPropertyChanged(nameof(SelectedSeriesToSnap));
}
}
public AnnotationCollection Annotations
{
get => _annotations;
set
{
_annotations = value;
OnPropertyChanged(nameof(Annotations));
}
}
private void InitializeChartSurface()
{
UpdatePriceChart();
ChartZoomModifier = ModifierType.RubberBandZoom;
ChartSeriesModifier = ModifierType.Rollover;
}
private void SetDefaults()
{
_chartType = ChartType.FastCandlestick;
_calendar = new DefaultDiscontinuousDateTimeCalendar();
_selectedCalendar = "Extended";
_selectedSeriesToSnap = "PriceData";
}
private static AnnotationCollection CreateAnnotations()
{
return new AnnotationCollection
{
new BuyMarkerAnnotation(),
new SellMarkerAnnotation(),
new LineAnnotation(),
new BoxAnnotation()
};
}
public ModifierType ChartSeriesModifier
{
get => _chartSeriesModifier;
set
{
_chartSeriesModifier = value;
OnPropertyChanged(nameof(ChartSeriesModifier));
OnPropertyChanged(nameof(IsRolloverSelected));
OnPropertyChanged(nameof(IsCursorSelected));
}
}
public ModifierType ChartZoomModifier
{
get => _chartZoomModifier;
set
{
_chartZoomModifier = value;
OnPropertyChanged(nameof(ChartZoomModifier));
OnPropertyChanged(nameof(IsZoomPanSelected));
OnPropertyChanged(nameof(IsRubberBandZoomSelected));
}
}
public ShowTooltipOptions ShowTooltipMode
{
get => _showTooltipMode;
set
{
_showTooltipMode = value;
OnPropertyChanged(nameof(ShowTooltipMode));
}
}
public SourceMode SourceMode
{
get => _sourceMode;
set
{
_sourceMode = value;
OnPropertyChanged(nameof(SourceMode));
}
}
public bool ShowAxisLabels
{
get => _showAxisLabels;
set
{
_showAxisLabels = value;
OnPropertyChanged(nameof(ShowAxisLabels));
}
}
public IDiscontinuousDateTimeCalendar Calendar
{
get => _calendar;
set
{
_calendar = value;
OnPropertyChanged(nameof(Calendar));
}
}
public string SelectedCalendar
{
get => _selectedCalendar;
set
{
_selectedCalendar = value;
UpdateCalendar(_selectedCalendar);
UpdatePriceChart();
OnPropertyChanged(nameof(SelectedCalendar));
}
}
private void UpdatePriceChart()
{
PriceSeries = (IOhlcDataSeries<DateTime, double>)_priceData.ToDiscontinuousSeries(Calendar);
// Create a series for the 200 period SMA which will be plotted as a line chart
Sma200Series = (IXyDataSeries<DateTime, double>)PriceSeries.ToMovingAverage(200);
// Create a series for the 50 period SMA which will be plotted as a line chart
Sma50Series = (IXyDataSeries<DateTime, double>)PriceSeries.ToMovingAverage(50);
// Update the chart type and timeframe with current settings
UpdateChartType(_chartType);
UpdateAnnotations();
_priceSeries.InvalidateParentSurface(RangeMode.ZoomToFit);
}
private void UpdateAnnotations()
{
var minIndex = PriceSeries.CloseValues.IndexOf(PriceSeries.CloseValues.Min());
var maxIndex = PriceSeries.CloseValues.IndexOf(PriceSeries.CloseValues.Max());
Annotations[0].X1 = PriceSeries.XValues[minIndex];
Annotations[0].Y1 = PriceSeries.YValues[minIndex];
Annotations[1].X1 = PriceSeries.XValues[maxIndex];
Annotations[1].Y1 = PriceSeries.YValues[maxIndex];
Annotations[2].X1 = PriceSeries.XValues[minIndex];
Annotations[2].Y1 = PriceSeries.YValues[minIndex];
Annotations[2].X2 = PriceSeries.XValues[maxIndex];
Annotations[2].Y2 = PriceSeries.YValues[maxIndex];
Annotations[3].X1 = PriceSeries.XValues[minIndex];
Annotations[3].Y1 = PriceSeries.YValues[minIndex];
Annotations[3].X2 = PriceSeries.XValues[maxIndex];
Annotations[3].Y2 = PriceSeries.YValues[maxIndex];
}
private void UpdateChartType(ChartType chartType)
{
if (PriceSeries.Count == 0)
{
UpdatePriceChart();
return;
}
SelectedChartType = chartType;
}
private void UpdateCalendar(string calendar)
{
if (calendar == "Extended")
{
Calendar = new DefaultDiscontinuousDateTimeCalendar();
}
else if (calendar == "NYSE")
{
Calendar = new NYSECalendar();
}
else if (calendar == "LSE")
{
Calendar = new LSECalendar();
}
}
}
}
using System;
using SciChart.Charting.Numerics.Calendars;
namespace SciChart.Examples.Examples.SeeFeaturedApplication.Common
{
/// <summary>
/// Example of how to make a Discontinuous DateTime Calender for the New York Stock Exchange
///
/// If you wish to extend this, ensure that public holidays are set for the year(s) which you wish to show data
/// e.g. https://www.redcort.com/us-federal-bank-holidays/
/// </summary>
public class NYSECalendar : DiscontinuousDateTimeCalendarBase
{
public NYSECalendar()
{
// For intraday data, you can add a skip range like this.
// For daily data, skip ranges will cause the Daily OHLC bars with timestamp at 0:00:00 to be skipped
//SkipDayTimeRange.Add(new TimeSpanRange(new TimeSpan(0, 0, 0), new TimeSpan(9, 30, 0))); // NYSE is open at 9:30 am EST
//SkipDayTimeRange.Add(new TimeSpanRange(new TimeSpan(16, 0, 0), new TimeSpan(24, 0, 0))); // NYSE is closed at 16:00 pm EST
// NYSE is closed on weekends
SkipDaysInWeek.Add(DayOfWeek.Saturday);
SkipDaysInWeek.Add(DayOfWeek.Sunday);
SkipDates.Add(new DateTime(2015, 12, 25)); // NYSE Closed on Christmas Day 2015
SkipDates.Add(new DateTime(2016, 1, 1)); // NYSE Closed on New years day 2016
SkipDates.Add(new DateTime(2016, 1, 15)); // NYSE Clsoed on Martin Luther King Day 2016
SkipDates.Add(new DateTime(2016, 11, 24)); // NYSE Closed on Thanksgiving 2016
}
}
/// <summary>
/// Example of how to make a Discontinuous DateTime Calender for the London Stock Exchange
///
/// If you wish to extend this, ensure that public holidays are set for the year(s) which you wish to show data
/// e.g. http://www.lseg.com/areas-expertise/our-markets/london-stock-exchange/equities-markets/trading-services/business-days
/// </summary>
public class LSECalendar : DiscontinuousDateTimeCalendarBase
{
public LSECalendar()
{
// For intraday data, you can add a skip range like this.
// For daily data, skip ranges will cause the Daily OHLC bars with timestamp at 0:00:00 to be skipped
//SkipDayTimeRange.Add(new TimeSpanRange(new TimeSpan(0, 0, 0), new TimeSpan(8, 0, 0))); // LSE is open at 08:00am GMT
//SkipDayTimeRange.Add(new TimeSpanRange(new TimeSpan(16, 30, 0), new TimeSpan(24, 0, 0))); // LSE is closed at 16:30pm GMT
// LSE is closed on weekends
SkipDaysInWeek.Add(DayOfWeek.Saturday);
SkipDaysInWeek.Add(DayOfWeek.Sunday);
SkipDates.Add(new DateTime(2015, 12, 25)); // LSE Closed on Christmas Day 2015
SkipDates.Add(new DateTime(2016, 1, 1)); // LSE Closed on New Years day 2016
}
}
}