CartesianChart Bar Series CombinedMode "Stack"

6 posts, 0 answers
  1. Gina
    Gina avatar
    5 posts
    Member since:
    Mar 2013

    Posted 23 Apr 2013 Link to this post

    Hello,
    I was wondering if there exists some option to customize the values of the Y axis when using bar series with combined mode stack or some option for stack mode to plot to corresponding points of Y axes. If I understood well when a bar series is in Stack mode the bar ignores the real values but it plots the distance between points in the series, putting all the portions one above another and create an enormous scale for the Y axis. I would like if possible that it takes the real values, cause they are sequential in my example, and make the correct scale with real values.
    I will explain my problem, so maybe you can give me an advice, maybe there is some other component or chart option, different series that I can use to solve my problem. I am using MVVM pattern and as I am not verry profound of code behind and would like to solve this problem in MVVM style.
    So I have a list of strands and each strand is divided in n zones that have start position, end position and a quality indicator. In base of this quality indicator each zone is colored with the specific color. The values of the start and end position are sequential, so that each point rappresents a single zone and i single colored portion on the stack bar. My idea was to create an collection of QcsStrandData in my viewmodel, and bind this collection to the item source of the bar series in the cartesian chart, setting the categoryBinding = "StrandNo" and ValueBinding = "ZoneEnd", in that way I achieved to have a single bar for each strand divided in the corresponding zones. I  managed to color the zone portions using the point Template and until here everything is perfect. The problem is that in this way the Y axes goes to the stars and not to the maximum value of the last point. I also manage somehow to bypass that, I defined and internal vertical ax inside the bar series and hide it, and used the general Y ax and bind it to a fixed maximum value. But then I noticed another problem that I miss the proportions, cause the portion on the bar is in proportion of distance between 2 points, so for example I have one zone from 4640 to 7920, the next one 7920 to 17115, the next from 17115 to 18215 but the height on the bar of all of this zones is the same and I would need it to be in proportion with the real values.
    The structure of the entity is
    public class QcsStrandData : BaseObject
        {
            private long stranNo;
            public long StrandNo
            {
                get { return this.stranNo; }
                set { this.stranNo = value; this.OnPropertyChanged("StrandNo"); }
            }
     
            private double zoneEnd;
            public double ZoneEnd
            {
                get { return this.zoneEnd; }
                set { this.zoneEnd = value; this.OnPropertyChanged("ZoneEnd"); }
            }
     
            private double zoneStart;
     
            public double ZoneStart
            {
                get { return zoneStart; }
                set { zoneStart = value; this.OnPropertyChanged("ZoneStart"); }
            }
     
     
            private Brush zoneQuality;
            public Brush ZoneQuality
            {
                get { return this.zoneQuality; }
                set { this.zoneQuality = value; this.OnPropertyChanged("ZoneQuality"); }
            }
     
            private string zoneName;
            public string ZoneName
            {
                get { return zoneName; }
                set { zoneName = value; this.OnPropertyChanged("ZoneName"); }
            }
        }
    The part of the viewModel that fills the collection is
    public ObservableCollection<QcsStrandData> QcsData
            {
                get { return qcsData; }
                set { qcsData = value; this.OnPropertyChanged("QcsData"); }
            }
     
     
            public ObservableCollection<QcsStrandData> CreateQcsStrandsData()
            {
                ObservableCollection<QcsStrandData> result = new ObservableCollection<QcsStrandData>();
     
                result.Add(new QcsStrandData() { ZoneName = "Tundish", StrandNo = 1, ZoneEnd = 100, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Mould", StrandNo = 1, ZoneEnd = 680, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 1", StrandNo = 1, ZoneEnd = 980, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 2", StrandNo = 1, ZoneEnd = 2830, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 3", StrandNo = 1, ZoneEnd = 4640, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 4", StrandNo = 1, ZoneEnd = 7920, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "AirCooling", StrandNo = 1, ZoneEnd = 17115, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Module1", StrandNo = 1, ZoneEnd = 18215, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module2", StrandNo = 1, ZoneEnd = 19315, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Module3", StrandNo = 1, ZoneEnd = 20415, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module4", StrandNo = 1, ZoneEnd = 21515, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Module5", StrandNo = 1, ZoneEnd = 22615, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module6", StrandNo = 1, ZoneEnd = 23715, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module7", StrandNo = 1, ZoneEnd = 24815, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Module8", StrandNo = 1, ZoneEnd = 25915, ZoneQuality = new SolidColorBrush(Colors.OrangeRed) });
                result.Add(new QcsStrandData() { ZoneName = "Module9", StrandNo = 1, ZoneEnd = 27015, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Tart", StrandNo = 1, ZoneEnd = 37395, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Tcm", StrandNo = 1, ZoneEnd = 46500, ZoneQuality = new SolidColorBrush(Colors.Lime) });
     
                result.Add(new QcsStrandData() { ZoneName = "Tundish", StrandNo = 2, ZoneEnd = 100, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Mould", StrandNo = 2, ZoneEnd = 680, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 1", StrandNo = 2, ZoneEnd = 980, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 2", StrandNo = 2, ZoneEnd = 2830, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 3", StrandNo = 2, ZoneEnd = 4640, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 4", StrandNo = 2, ZoneEnd = 7920, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "AirCooling", StrandNo = 2, ZoneEnd = 17115, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Module1", StrandNo = 2, ZoneEnd = 18215, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module2", StrandNo = 2, ZoneEnd = 19315, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Module3", StrandNo = 2, ZoneEnd = 20415, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module4", StrandNo = 2, ZoneEnd = 21515, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Module5", StrandNo = 2, ZoneEnd = 22615, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module6", StrandNo = 2, ZoneEnd = 23715, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module7", StrandNo = 2, ZoneEnd = 24815, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Module8", StrandNo = 2, ZoneEnd = 25915, ZoneQuality = new SolidColorBrush(Colors.OrangeRed) });
                result.Add(new QcsStrandData() { ZoneName = "Module9", StrandNo = 2, ZoneEnd = 27015, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Tart", StrandNo = 2, ZoneEnd = 37395, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Tcm", StrandNo = 2, ZoneEnd = 46500, ZoneQuality = new SolidColorBrush(Colors.Lime) });
     
                result.Add(new QcsStrandData() { ZoneName = "Tundish", StrandNo = 3, ZoneEnd = 100, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Mould", StrandNo = 3, ZoneEnd = 680, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 1", StrandNo = 3, ZoneEnd = 980, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 2", StrandNo = 3, ZoneEnd = 2830, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 3", StrandNo = 3, ZoneEnd = 4640, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Zone 4", StrandNo = 3, ZoneEnd = 7920, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "AirCooling", StrandNo = 3, ZoneEnd = 17115, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Module1", StrandNo = 3, ZoneEnd = 18215, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module2", StrandNo = 3, ZoneEnd = 19315, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Module3", StrandNo = 3, ZoneEnd = 20415, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module4", StrandNo = 3, ZoneEnd = 21515, ZoneQuality = new SolidColorBrush(Colors.Orange) });
                result.Add(new QcsStrandData() { ZoneName = "Module5", StrandNo = 3, ZoneEnd = 22615, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module6", StrandNo = 3, ZoneEnd = 23715, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Module7", StrandNo = 3, ZoneEnd = 24815, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Module8", StrandNo = 3, ZoneEnd = 25915, ZoneQuality = new SolidColorBrush(Colors.OrangeRed) });
                result.Add(new QcsStrandData() { ZoneName = "Module9", StrandNo = 3, ZoneEnd = 27015, ZoneQuality = new SolidColorBrush(Colors.Red) });
                result.Add(new QcsStrandData() { ZoneName = "Tart", StrandNo = 3, ZoneEnd = 37395, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                result.Add(new QcsStrandData() { ZoneName = "Tcm", StrandNo = 3, ZoneEnd = 46500, ZoneQuality = new SolidColorBrush(Colors.Lime) });
                return result;
            }
    and the xaml code for the chart
    <telerik:RadCartesianChart x:Name="chart" Margin="5">
                    <telerik:RadCartesianChart.Grid>
                        <chartView:CartesianChartGrid MajorLinesVisibility="Y" MajorYLineDashArray="5,5" />
                    </telerik:RadCartesianChart.Grid>
                    <telerik:RadCartesianChart.VerticalAxis>
                                <chartView:LinearAxis Visibility="Visible" ShowLabels="True" Title="Distance [mm]" Minimum="0" IsInverse="True"/>
                    </telerik:RadCartesianChart.VerticalAxis>
                    <telerik:RadCartesianChart.HorizontalAxis>
                                <chartView:CategoricalAxis ShowLabels="True" VerticalLocation="Top" Title="Strand" PlotMode="BetweenTicks" GapLength="{Binding StrandGap}"/>
                            </telerik:RadCartesianChart.HorizontalAxis>
                    <telerik:RadCartesianChart.Series>
                                <chartView:BarSeries CategoryBinding="StrandNo" ValueBinding="ZoneEnd" ItemsSource="{Binding QcsData}" CombineMode="Stack">
                                    <chartView:BarSeries.PointTemplate>
                                        <DataTemplate>
                                            <Border Background="{Binding DataItem.ZoneQuality}" BorderThickness="0,2,0,0"  BorderBrush="Black"/>
                                        </DataTemplate>
                                    </chartView:BarSeries.PointTemplate>
                                </chartView:BarSeries>
                            </telerik:RadCartesianChart.Series>
                </telerik:RadCartesianChart>
    I also attach 2 jpgs wpfStrandZones with the result that I obtain with the source code above and the strandZones that is the screen of what I would need to have.
    Any suggestion would be appreciated.
    Thanks


      
  2. Evgenia
    Admin
    Evgenia avatar
    1407 posts

    Posted 26 Apr 2013 Link to this post

    Hi Gina,

     Note that Stacked Bars Chart show the relationship of individual items to the whole, comparing the contribution of each value to a total across categories. It is not suitable for the scenario you have. What I'm suggesting is that you use Range Bar series instead. Here's a sample with source code provided that should help you understand Range series.

    Kind regards,
    Evgenia
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Gina
    Gina avatar
    5 posts
    Member since:
    Mar 2013

    Posted 07 May 2013 Link to this post

    Hi Evgenia,
    First  off all  thanks for the reply and sorry that I am replying only now, but until now I didn't have the time to try your solution with the RangeBarSeries, cause there was an emergency and I was moved to another project, but I am back now.
    So I tryed this RangeBarSeries, the range is drawn correcly, but each range for the same category is shifted right by the width of the bar, so I have a "step" range bar. Is there some propery to force the range bar that for the same category creates a linear stack i.e. it puts all the ranges one above another? I tryed set Combined Mode to stack, and hopping the this will align all category ranges, but it didin't help. Although I think this property is ignored for the RangeBarSeries.This is how I changed the xaml the rest remain the same as in my previous post.
    Am I missing something?
    <telerik:RadCartesianChart x:Name="chart" Margin="5">
                    <telerik:RadCartesianChart.Grid>
                        <chartView:CartesianChartGrid MajorLinesVisibility="Y" MajorYLineDashArray="5,5" />
                    </telerik:RadCartesianChart.Grid>
                    <telerik:RadCartesianChart.VerticalAxis>
                                <chartView:LinearAxis Visibility="Visible" ShowLabels="True" Title="Distance [mm]" Minimum="0" IsInverse="True"/>
                    </telerik:RadCartesianChart.VerticalAxis>
                    <telerik:RadCartesianChart.HorizontalAxis>
                                <chartView:CategoricalAxis ShowLabels="True" VerticalLocation="Top" Title="Strand"  />
                            </telerik:RadCartesianChart.HorizontalAxis>
                    <telerik:RadCartesianChart.Series>
                                <chartView:RangeBarSeries CategoryBinding="StrandNo" HighBinding="ZoneEnd" LowBinding="ZoneStart" ItemsSource="{Binding QcsData}" CombineMode="Stack" >
                                    <chartView:RangeBarSeries.PointTemplate>
                                        <DataTemplate>
                                            <Rectangle Fill="{Binding DataItem.ZoneQuality}"/>
                                        </DataTemplate>
                                    </chartView:RangeBarSeries.PointTemplate>
                                </chartView:RangeBarSeries>
                            </telerik:RadCartesianChart.Series>
                </telerik:RadCartesianChart>

    Sorry that I am buging you but there is verry small amount of examples for the RangeBarSeries.
    Thanks
    Gina
  5. Gina
    Gina avatar
    5 posts
    Member since:
    Mar 2013

    Posted 07 May 2013 Link to this post

    Hi again Evgenia,
    Maybe I found a possible solution, it is not the most elegant but it works. As I have this chart only in visualization it could also stay like that. Instead of the rangeBarSeries I tryed the range series and this seems to be working. The only problem is that the range series connects with some sort of area the last point of the one category to the first point of the category that follows. I fixed this setting the "Fill" property of the range series to transparent and obtained the desired result. It is not the best solution but it is working. Anyway I would appreciate if you could give me an answer why the RangeBarSeries is making this "step" bar and if it's possible to make it work as a StackBar. It is not urgent so take your time.
    Here is my non elegant xaml if somebody needs it.
    <telerik:RadCartesianChart x:Name="chart" Margin="5">
                    <telerik:RadCartesianChart.Grid>
                        <chartView:CartesianChartGrid MajorLinesVisibility="Y" MajorYLineDashArray="5,5" />
                    </telerik:RadCartesianChart.Grid>
                    <telerik:RadCartesianChart.VerticalAxis>
                                <chartView:LinearAxis Visibility="Visible" ShowLabels="True" Title="Distance [mm]" Minimum="0" IsInverse="True"/>
                    </telerik:RadCartesianChart.VerticalAxis>
                    <telerik:RadCartesianChart.HorizontalAxis>
                                <chartView:CategoricalAxis ShowLabels="True" VerticalLocation="Top" Title="Strand"  PlotMode="BetweenTicks" GapLength="0.75" />
                            </telerik:RadCartesianChart.HorizontalAxis>
                    <telerik:RadCartesianChart.Series>
                                <chartView:RangeSeries CategoryBinding="StrandNo" HighBinding="ZoneEnd" LowBinding="ZoneStart" ItemsSource="{Binding QcsData}" Fill="Transparent" >
                                    <chartView:RangeSeries.PointTemplate>
                                        <DataTemplate>
                                            <Border  Background="{Binding DataItem.ZoneQuality}" BorderBrush="Black" BorderThickness="0,2,0,0" />
                                        </DataTemplate>
                                    </chartView:RangeSeries.PointTemplate>
                                </chartView:RangeSeries>
                            </telerik:RadCartesianChart.Series>
                </telerik:RadCartesianChart>

    Thanks
    Best Regards
    Gina
  6. Evgenia
    Admin
    Evgenia avatar
    1407 posts

    Posted 13 May 2013 Link to this post

    Hello Gina,

     You may still achieve your scenario with RangeBar series. However to avoid clustering and to make them look as they are stacked you need to set the CombineMode property of the series to None.

    Regards,
    Evgenia
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  7. Gina
    Gina avatar
    5 posts
    Member since:
    Mar 2013

    Posted 13 May 2013 Link to this post

    Thanks a lot Evgenia. The combine mode to none worked just fine, it's what I was looking for.
    Best regards
    Gina
Back to Top
UI for WPF is Visual Studio 2017 Ready