Controlling bar segment width in stacked bar RadCartesianChart

6 posts, 0 answers
  1. Scott
    Scott avatar
    11 posts
    Member since:
    Oct 2012

    Posted 03 Mar 2014 Link to this post

    I have two stacked bar charts displayed side-by-side, as shown in the attached image.  I need for the bar width to be the same between both charts.  The examples I've found show to do this for the entire bar by setting the point template, for example:

    <chartView:BarSeries.PointTemplate>                     
        <DataTemplate>                         
           <Rectangle Fill="{Binding myFill} Width="50"/>                     
       </DataTemplate>                 
    </chartView:BarSeries.PointTemplate>

    This doesn't work for me because the template only gives me access to the entire bar and not each individual segment (each segment of the bar has its own fill color).  How can I achieve my goal?  Can I turn off the auto-sizing of the bars?  Can I somehow access the template for each individual segment of the stacked bar, rather than the template for the entire bar?  Can I set the widths in the DataBindingComplete event of the BarSeries object?

    Thanks,
    Scott
  2. Martin
    Admin
    Martin avatar
    1099 posts

    Posted 05 Mar 2014 Link to this post

    Hello Scott,

    There are a few approaches you can use to achieve your requirement. You can change the size of the bars by setting the GapLength property of the axis. This property controls how much free space should remain from the category slot after the bar is added.

    You can also set a PointTemplate for each bar in the BarSeries if you use the BarSeries.PointTemplates collection which contains DataTemplates for all DataPoints. You can see how to use this collection in the BarSeries help article. In addition here is an example:
    <telerik:BarSeries.PointTemplates>
        <DataTemplate>
            <Rectangle Fill="Red" Width="50"/>                    
       </DataTemplate>
        <DataTemplate>
            <Rectangle Fill="Green" Width="50"/>
        </DataTemplate>
    </telerik:BarSeries.PointTemplates>

    Another approach can be to set the DefaultVisualStyle property of the BarSeries. This will set the style for each bar in the series.
    <UserControl.Resources>
        <Style x:Key="barStyle" TargetType="Border">
            <Setter Property="MaxWidth" Value="50" />
            <Setter Property="Background" Value="{Binding DataItem.Fill}"/>
        </Style>
    </UserControl.Resources>

    .........

    <telerik:BarSeries CombineMode="Stack"
               ItemsSource="{Binding Items}"   
               
    ValueBinding="Value"               
               
    CategoryBinding="Category"               
               
    DefaultVisualStyle="{StaticResource barStyle}"/>
    ......

    You can see the implementation with the DefaultVisualStyle in the attached project.

    Regards,
    Martin
    Telerik

    DevCraft Q1'14 is here! Join the free online conference to see how this release solves your top-5 .NET challenges. Reserve your seat now!

  3. DevCraft banner
  4. linnet
    linnet avatar
    8 posts
    Member since:
    Dec 2010

    Posted 04 May 2014 in reply to Martin Link to this post

    Hello,
    I tried secend approach whitch used DefaultVisualStyle property of the BarSeries to change bar width.
    It's worked, but I can't let the bar move to center.

    Thank you for the support!
  5. Peshito
    Admin
    Peshito avatar
    497 posts

    Posted 05 May 2014 Link to this post

    Hello linnet,

    From the image attached I assume that you are using DateTimeContinuous axis. If this is so, please try using a DateTimeCategorical axis instead and see how it goes. With continuous axis, the data is sorted chronologically and displayed in accordance of the date time factor which combined with stacked bars will result in the scenario you have.

    Hope this helps.

    Regards,
    Peshito
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  6. linnet
    linnet avatar
    8 posts
    Member since:
    Dec 2010

    Posted 06 May 2014 in reply to Peshito Link to this post

    Hello Peshito,
    I'm sorry for did not attached code on reply.
    From that image attached, I used Categorical Axis and the value in XAxis may not be "2013, 2014", but "Group A, Group B".
    On Attached file(illustration.png) I set the bar size, but I still want move the bar to center where upon the "Group A, Group B".

    Here is my code:

    ChartView.xaml
    <UserControl.DataContext>
        <my:ChartViewModel />
    </UserControl.DataContext>
     
    <UserControl.Resources>
        <Style x:Key="barStyle" TargetType="Border">
            <Setter Property="MaxWidth" Value="40"></Setter>
            <Setter Property="Background" Value="{Binding DataItem.Fill}"/>
        </Style>
    </UserControl.Resources>
     
    <telerik:RadCartesianChart x:Name="chart" Grid.Row="0" Grid.Column="0" Height="Auto" Palette="Summer">
        <telerik:RadCartesianChart.HorizontalAxis>
            <telerik:CategoricalAxis></telerik:CategoricalAxis>
        </telerik:RadCartesianChart.HorizontalAxis>
     
        <telerik:RadCartesianChart.VerticalAxis>
            <telerik:LinearAxis x:Name="verticalAxis"  />
        </telerik:RadCartesianChart.VerticalAxis>
     
        <telerik:BarSeries ItemsSource="{Binding Data}"
                                 ValueBinding="Value"
                                 CategoryBinding="XValue"
                                 CombineMode="Stack"
                                 ShowLabels="False"
                                 FontSize="10" DefaultVisualStyle="{StaticResource barStyle}">
            <telerik:BarSeries.LegendSettings>
                <telerik:SeriesLegendSettings Title="{Binding SeriesTitle1}" />
            </telerik:BarSeries.LegendSettings>
        </telerik:BarSeries>
        <telerik:BarSeries ItemsSource="{Binding Data2}"
                                 ValueBinding="Value"
                                 CategoryBinding="XValue"
                                 CombineMode="Stack"
                                 ShowLabels="False"
                                 FontSize="10" DefaultVisualStyle="{StaticResource barStyle}">
            <telerik:BarSeries.LegendSettings>
                <telerik:SeriesLegendSettings Title="{Binding SeriesTitle2}" />
            </telerik:BarSeries.LegendSettings>
        </telerik:BarSeries>
    </telerik:RadCartesianChart>

    ChartViewModel.cs
    public class ChartViewModel : INotifyPropertyChanged
    {
        private string _title = string.Empty;
        private string _seriesTitle1 = string.Empty;
        private string _seriesTitle2 = string.Empty;
     
        public IEnumerable<ChartData> Data
        {
            get;
            set;
        }
     
        public IEnumerable<ChartData> Data2
        {
            get;
            set;
        }
     
        public string Title
        {
            get
            {
                return this._title;
            }
            set
            {
                if (this._title != value)
                {
                    this._title = value;
                    this.OnPropertyChanged("Title");
                }
            }
        }
     
        public string SeriesTitle1
        {
            get
            {
                return this._seriesTitle1;
            }
            set
            {
                if (this._seriesTitle1 != value)
                {
                    this._seriesTitle1 = value;
                    this.OnPropertyChanged("SeriesTitle1");
                }
            }
        }
     
        public string SeriesTitle2
        {
            get
            {
                return this._seriesTitle2;
            }
            set
            {
                if (this._seriesTitle2 != value)
                {
                    this._seriesTitle2 = value;
                    this.OnPropertyChanged("SeriesTitle2");
                }
            }
        }
     
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
     
        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
     
    public class ChartData
    {
        public string XValue
        {
            get;
            set;
        }
     
        public string YValue
        {
            get;
            set;
        }
     
        public string ZValue
        {
            get;
            set;
        }
     
        public decimal? Value
        {
            get;
            set;
        }
    }

    MainPage.xaml
    <my:ChartView x:Name="chart"></my:ChartView>

    MainPage.xaml.cs
    public partial class MainPage : UserControl
    {
        private int? seed = null;
     
        public MainPage()
        {
            InitializeComponent();
     
            var vm4 = new ChartViewModel()
            {
                Title = "Analysis",
                SeriesTitle1 = "S1",
                SeriesTitle2 = "S2",
                Data = GetChart4Data(11000, 12000),
                Data2 = GetChart4Data(1300, 1800)
            };
            chart.DataContext = vm4;
        }
     
     
        public IEnumerable<ChartData> GetChart4Data(int min, int max)
        {
            if (seed == null)
            {
                seed = DateTime.Now.Millisecond;
            }
            else
            {
                seed += 1;
            }
            //var xvalue = new List<string>() { "2013", "2014" };
            var xvalue = new List<string>() { "Group A", "Group B" };
            var result = new List<ChartData>();
            var rand = new Random(seed.Value);
            foreach (var item in xvalue)
            {
                result.Add(new ChartData()
                {
                    XValue = item,
                    Value = rand.Next(min, max)
                });
            }
            return result;
        }
    }

    Thank you for the support.





  7. Peshito
    Admin
    Peshito avatar
    497 posts

    Posted 07 May 2014 Link to this post

    Hi linnet,

    Thank you for the provided sample code. This helped me in locating where the issue is.

    Using DefaultVisualStyle for your BarSeries will not fully work in your scenario because the chart specifies the size of the bars first which has higher priority over setting them with a style. However using PointTemplate as I see you did at first place, should work for you.

    Below is modified version of your code:
    ChartView.xaml
    <UserControl.Resources>
        <DataTemplate x:Key="pointTemplate">
            <Rectangle Fill="{Binding ElementName=chart, Path=Palette.GlobalEntries[0].Fill}" Width="40"/>
        </DataTemplate>
        <DataTemplate x:Key="pointTemplate2">
            <Rectangle Fill="{Binding ElementName=chart, Path=Palette.GlobalEntries[1].Fill}" Width="40"/>
        </DataTemplate>
    </UserControl.Resources>
    This will set the width of your bars to be 40 pixels and the color of each bar series will be consistent with the color from the global chart's palette.

    <telerik:BarSeries ItemsSource="{Binding Data}"
                                ValueBinding="Value"
                                CategoryBinding="XValue"
                                CombineMode="Stack"
                                ShowLabels="False"
                                FontSize="10" PointTemplate="{StaticResource pointTemplate}" >
                   <telerik:BarSeries.LegendSettings>
                       <telerik:SeriesLegendSettings Title="{Binding SeriesTitle1}" />
                   </telerik:BarSeries.LegendSettings>
               </telerik:BarSeries>
               <telerik:BarSeries ItemsSource="{Binding Data2}"
                                ValueBinding="Value"
                                CategoryBinding="XValue"
                                CombineMode="Stack"
                                ShowLabels="False"
                                FontSize="10" PointTemplate="{StaticResource pointTemplate2}" >
    Please give this approach a try and let me know if further questions arise.

    Regards,
    Peshito
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
Back to Top
DevCraft banner