Any plans to implement this feature?
Any suggestions what to do with such a charts?
In our web-app we are using DX chart and this GREAT feature http://community.devexpress.com/blogs/ctodx/archive/2009/06/23/sneak-peek-scale-breaks-in-winforms-and-web-charts.aspx
Your controls are great, but scale break feature is must have for financial data.
Hi Sergey,
We don't have Scale Breaks in the current version, but it is on the backlog for this year. Our 10.2 release in June won't include this feature, but look for the 10.3 release in October for this.
Let me know if there is anything else I can help you with,
Thanks
Jason
Hi Jason,
Are there any news on this? We are evaluating Infragistics among its competitors and the support for scale breaks will be key in driving our choice.
Best regards,
Gabriele Giuseppini
Grabiele,
You can find the public roadmap here: https://es.infragistics.com/products/all
You might be interested to know that with a bit work you can implement a version of y scale breaks on the current version of the xamDataChart. I'll provide a sample below:
Xaml:
<UserControl.Resources> <local:TestData x:Key="data" /> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <local:XamDataChartWithYBreaks> <local:XamDataChartWithYBreaks.Breaks> <local:Range Start="10" End="490" /> </local:XamDataChartWithYBreaks.Breaks> <local:XamDataChartWithYBreaks.ChartTemplate> <DataTemplate> <igChart:XamDataChart x:Name="chart" HorizontalAlignment="Stretch"> <igChart:XamDataChart.Axes> <igChart:CategoryXAxis x:Name="xAxis" ItemsSource="{StaticResource data}" Label="{}{Label}" /> <igChart:NumericYAxis x:Name="yAxis" /> </igChart:XamDataChart.Axes> <igChart:XamDataChart.Series> <igChart:ColumnSeries x:Name="column" ItemsSource="{StaticResource data}" XAxis="{Binding ElementName=xAxis}" YAxis="{Binding ElementName=yAxis}" ValueMemberPath="Value" /> </igChart:XamDataChart.Series> </igChart:XamDataChart> </DataTemplate> </local:XamDataChartWithYBreaks.ChartTemplate> </local:XamDataChartWithYBreaks> </Grid>
And Code behind:
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } } public class TestDataItem { public string Label { get; set; } public double Value { get; set; } } public class TestData : ObservableCollection<TestDataItem> { private static Random _rand = new Random(); public TestData() { Add(new TestDataItem() { Label = "A", Value = 1 }); Add(new TestDataItem() { Label = "B", Value = 4 }); Add(new TestDataItem() { Label = "C", Value = 491 }); Add(new TestDataItem() { Label = "D", Value = 500 }); Add(new TestDataItem() { Label = "E", Value = 5 }); Add(new TestDataItem() { Label = "F", Value = 3 }); } } public class JaggedBreach : ContentControl { private Polyline _path = new Polyline(); private static Random _rand = new Random(); public JaggedBreach() { List<Point> pointsBelow = new List<Point>(); List<Point> pointsAbove = new List<Point>(); double currY = 5.0; for (int i = 0; i < 80; i++) { double x = 1.0 * (i / 80.0); if (_rand.NextDouble() > .5) { currY += _rand.NextDouble(); } else { currY -= _rand.NextDouble(); } if (currY < 0) { currY = 0; } if (currY > 10) { currY = 10; } double y = currY; pointsBelow.Add(new Point() { X = x, Y = y }); pointsAbove.Add(new Point() { X = x, Y = 10 + y }); } _path.Stretch = Stretch.Fill; var brush = new LinearGradientBrush(); brush.GradientStops.Add(new GradientStop() { Color = Colors.LightGray }); brush.GradientStops.Add(new GradientStop() { Color = Colors.Gray, Offset = 1 }); _path.Fill = brush; _path.StrokeThickness = .5; _path.Stroke = new SolidColorBrush(Colors.DarkGray); this.HorizontalContentAlignment = HorizontalAlignment.Stretch; this.VerticalContentAlignment = VerticalAlignment.Stretch; this.Height = 25; this.Content = _path; foreach (var point in pointsAbove) { _path.Points.Add(point); } pointsBelow.Reverse(); foreach (var point in pointsBelow) { _path.Points.Add(point); } _path.Points.Add(pointsAbove.First()); } } public class XamDataChartWithYBreaks : ContentControl { private StackPanel _content = new StackPanel(); public XamDataChartWithYBreaks() { _breaks = new BreakCollection(); _breaks.CollectionChanged += Breaks_CollectionChanged; this.HorizontalContentAlignment = HorizontalAlignment.Stretch; this.VerticalContentAlignment = VerticalAlignment.Stretch; this.Content = _content; this.SizeChanged += XamDataChartWithYBreaks_SizeChanged; } void XamDataChartWithYBreaks_SizeChanged( object sender, SizeChangedEventArgs e) { UpdateChartHeights(); } void Breaks_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e) { UpdateContent(); } private DataTemplate _chartTemplate; public DataTemplate ChartTemplate { get { return _chartTemplate; } set { _chartTemplate = value; UpdateContent(); } } private BreakCollection _breaks; public BreakCollection Breaks { get { return _breaks; } } private Guid _syncChannel = Guid.NewGuid(); private void UpdateContent() { if (ChartTemplate == null) { return; } foreach (XamDataChart chart in _content.Children.OfType<XamDataChart>()) { NumericYAxis yAxis = GetYAxis(chart); if (yAxis != null) { yAxis.RangeChanged -= yAxis_RangeChanged; } } _content.Children.Clear(); var ranges = GetRanges(); XamDataChart last = null; foreach (var range in ranges.Reverse()) { XamDataChart chart = GetChartForRange(range); if (chart == null) { continue; } last = chart; if (_content.Children.Count > 0) { _content.Children.Add(new JaggedBreach()); } _content.Children.Add(chart); } if (last != null) { CategoryAxisBase xAxis = GetXAxis(last); xAxis.LabelSettings.Visibility = Visibility.Visible; } } private XamDataChart GetChartForRange(Range range) { XamDataChart chart = ChartTemplate.LoadContent() as XamDataChart; if (chart == null) { return null; } NumericYAxis yAxis = GetYAxis(chart); if (yAxis == null) { return null; } yAxis.RangeChanged += yAxis_RangeChanged; if (range.Start != double.MinValue) { yAxis.MinimumValue = range.Start; } if (range.End != double.MaxValue) { yAxis.MaximumValue = range.End; } yAxis.LabelSettings.Extent = 50; chart.VerticalZoomable = false; chart.VerticalZoombarVisibility = Visibility.Collapsed; chart.HorizontalZoombarVisibility = Visibility.Collapsed; chart.HorizontalZoomable = true; CategoryAxisBase xAxis = GetXAxis(chart); if (xAxis == null) { return null; } xAxis.LabelSettings.Visibility = Visibility.Collapsed; SyncManager.SetSyncSettings(chart, new SyncSettings() { SyncChannel = _syncChannel.ToString(), SynchronizeHorizontally = true, SynchronizeVertically = false }); return chart; } void yAxis_RangeChanged( object sender, AxisRangeChangedEventArgs e) { UpdateChartHeights(); } private void UpdateChartHeights() { double totalRange = 0.0; int count = 0; foreach (XamDataChart chart in _content.Children.OfType<XamDataChart>()) { var yAxis = GetYAxis(chart); totalRange += yAxis.ActualMaximumValue - yAxis.ActualMinimumValue; count++; } double unusable = 0.0; if (count > 1) { unusable = (count - 1) * 25.0; } foreach (XamDataChart chart in _content.Children.OfType<XamDataChart>()) { var yAxis = GetYAxis(chart); double percentRange = (yAxis.ActualMaximumValue - yAxis.ActualMinimumValue) / totalRange; chart.Height = (this.ActualHeight - unusable) * percentRange; } } private CategoryAxisBase GetXAxis(XamDataChart chart) { return chart.Axes.OfType<CategoryAxisBase>().FirstOrDefault(); } private NumericYAxis GetYAxis(XamDataChart chart) { return chart.Axes.OfType<NumericYAxis>().FirstOrDefault(); } private IEnumerable<Range> GetRanges() { if (Breaks.Count < 1) { yield return new Range() { Start = double.MinValue, End = double.MaxValue }; yield break; } yield return new Range() { Start = double.MinValue, End = Breaks.First().Start }; for (int i = 0; i < Breaks.Count; i++) { if (i + 1 < Breaks.Count) { yield return new Range() { Start = Breaks[i].End, End = Breaks[i + 1].Start }; } else { yield return new Range() { Start = Breaks[i].End, End = double.MaxValue }; } } } } public class BreakCollection : ObservableCollection<Range> { } public class Range : DependencyObject { public static readonly DependencyProperty StartProperty = DependencyProperty.Register( "Start", typeof(double), typeof(Range), new PropertyMetadata(0.0)); public double Start { get { return (double)(GetValue(StartProperty)); } set { SetValue(StartProperty, value); } } public static readonly DependencyProperty EndProperty = DependencyProperty.Register( "End", typeof(double), typeof(Range), new PropertyMetadata(0.0)); public double End { get { return (double)(GetValue(EndProperty)); } set { SetValue(EndProperty, value); } } }
Pretty neat, huh? Hope this helps!
-Graham
The scalebreak feature is not a native feature of the xamWebChart or the xamDataChart. However, you can emulate it by using multiple charts, as the above sample does.
In the 10.3 version of the xamWebChart, I don't see any scale break feature. Where is this property located?