borders around clustered/stacked bars

11 posts, 0 answers
  1. Joe
    Joe avatar
    11 posts
    Member since:
    May 2014

    Posted 01 Jul 2014 Link to this post

    I was wondering how to style dynamically-created clustered/stacked bar charts (created using ChartSeriesProvider), so that there is a border around each bar (i.e., be able to set BorderBrush and BorderThickness properties).  Here is a code snipped of the *.xaml without borders.

    <telerik:RadCartesianChart.SeriesProvider>
                   <telerik:ChartSeriesProvider Source="{Binding Data}">
                       <telerik:ChartSeriesProvider.SeriesDescriptors>
                           <telerik:CategoricalSeriesDescriptor ItemsSourcePath="Data" ValuePath="Sales" CategoryPath="Article">
                               <telerik:CategoricalSeriesDescriptor.Style>
                                   <Style TargetType="telerik:BarSeries">
                                       <Setter Property="CombineMode" Value="Stack" />
                                       <Setter Property="local:ChartUtilities.SeriesStackGroupKey" Value="{Binding StackGroup}" />
                                       <Setter Property="LegendSettings">
                                           <Setter.Value>
                                               <telerik:SeriesLegendSettings Title="{Binding NameInLegend}"/>
                                           </Setter.Value>
                                       </Setter>
                                   </Style>
                               </telerik:CategoricalSeriesDescriptor.Style>
                           </telerik:CategoricalSeriesDescriptor>
                       </telerik:ChartSeriesProvider.SeriesDescriptors>
                   </telerik:ChartSeriesProvider>


    Thanks!
  2. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 03 Jul 2014 Link to this post

    Hi Joe,

    The BarSeries have a DefaultVisualStyle property which expects a Style targeting a Border. In this style you can set the fill, the border brush and the border thickness as per requirements.

    Regards,
    Petar Marchev
    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.
     
  3. UI for WPF is Visual Studio 2017 Ready
  4. Joe
    Joe avatar
    11 posts
    Member since:
    May 2014

    Posted 03 Jul 2014 in reply to Petar Marchev Link to this post

    Yes, that works fine for explicit BarSeries, but I can't figure out how to do it for dynamic series.

    How do you apply that style to the dynamic bar charts produced using a ChartSeriesProvider?  See my sample code above.

    Thanks!
  5. Joe
    Joe avatar
    11 posts
    Member since:
    May 2014

    Posted 03 Jul 2014 Link to this post

    OK, I got it to work!  For anyone else with this issue, here's the relevant code:

    <telerik:ChartSeriesProvider.SeriesDescriptors>
                            <telerik:CategoricalSeriesDescriptor ItemsSourcePath="SubcategoryData" ValuePath="Value" CategoryPath="Category">
                                <telerik:CategoricalSeriesDescriptor.Style>
                                    <Style TargetType="telerik:BarSeries">
                                        <Setter Property="DefaultVisualStyle">
                                            <Setter.Value>
                                                <Style TargetType="Border">
                                                    <Setter Property="BorderBrush" Value="Black"/>
                                                    <Setter Property="BorderThickness" Value="1"/>
                                                </Style>
                                            </Setter.Value>                                      
                                        </Setter>
    ...
  6. Renier Pretorius
    Renier Pretorius avatar
    46 posts
    Member since:
    Apr 2010

    Posted 05 Nov 2015 Link to this post

    Hi,

     I am trying to set the background color of a bar series generated from a ChartSeriesProvider. When explicitly setting the color as follows:

    <telerik:CategoricalSeriesDescriptor ItemsSourcePath="SeriesData" ValuePath="Value" CategoryPath="Label">
        <telerik:CategoricalSeriesDescriptor.Style>
            <Style TargetType="telerik:BarSeries" BasedOn="{StaticResource BarSeriesStyle}">
                <Setter Property="CombineMode" Value="Stack" />
                <Setter Property="DisplayName" Value="{Binding SeriesLabel}" />
                <Setter Property="LegendSettings">
                    <Setter.Value>
                        <telerik:SeriesLegendSettings Title="{Binding SeriesLabel}" />
                    </Setter.Value>
                </Setter>
                <Setter Property="DefaultVisualStyle">
                    <Setter.Value>
                        <Style TargetType="Border">
                            <Setter Property="Background" Value="Red"/>
                            <!--<Setter Property="Background" Value="{Binding SeriesBrush}"/>-->
                        </Style>
                    </Setter.Value>
                </Setter>
            </Style>
        </telerik:CategoricalSeriesDescriptor.Style>
    </telerik:CategoricalSeriesDescriptor>

    It works as expected with all series generated in red. However, when I try to dynamically bind it to a Brush property of the ViewModel, no background is set. See attached screenshots.

     FYI here is my ViewModel object

    public class ChartSeriesProviderSource : BindableBase
    {
        public AddRangeObservableCollection<CategoryDataPoint> SeriesData { get; private set; }
     
        public ChartSeriesProviderSource()
        {
            SeriesData = new AddRangeObservableCollection<CategoryDataPoint>();
            HasData = false;
        }
     
     
        private string _seriesLabel;
        public string SeriesLabel
        {
            get { return _seriesLabel; }
            set
            {
                if (value != _seriesLabel)
                {
                    _seriesLabel = value;
                    OnPropertyChanged(() => SeriesLabel);
                }
            }
        }
     
        private string _seriesColorString;
        public string SeriesColorString
        {
            get { return _seriesColorString; }
            set
            {
                if (value != _seriesColorString)
                {
                    _seriesColorString = value;
                    OnPropertyChanged(() => SeriesColorString);
                }
            }
        }
     
        private Brush _seriesBrush;
        public Brush SeriesBrush
        {
            get { return _seriesBrush; }
            set
            {
                if (value != _seriesBrush)
                {
                    _seriesBrush = value;
                    OnPropertyChanged(() => SeriesBrush);
                }
            }
        }
     
        private int _seriesOrder;
        public int SeriesOrder
        {
            get { return _seriesOrder; }
            set
            {
                if (value != _seriesOrder)
                {
                    _seriesOrder = value;
                    OnPropertyChanged(() => SeriesOrder);
                }
            }
        }
     
        private bool _hasData;
        public bool HasData
        {
            get { return _hasData; }
            set
            {
                if (value != _hasData)
                {
                    _hasData = value;
                    OnPropertyChanged(() => HasData);
                }
            }
        }
    }

     The number of series can vary greatly base on data filters applied so I do not want to get into manipulating the palette which I explicitly set to null

    <telerik:RadCartesianChart x:Name="chartAtoB" Palette="{x:Null}" Margin="3">
    Anyone with any idea on what I am doing wrong? 

     

     

  7. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 05 Nov 2015 Link to this post

    Hello Renier,

    You can use a debugger converter, in the binding that does not work as you expect it to, in order to see what is the actual incoming value. It should be the DataPoint of the bar, not the main view model or the series view model. You should be able to use an ElementName or RelativeSource binding in order to get the data context you are looking for. Let us know how it goes.

    Regards,
    Petar Marchev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  8. Renier Pretorius
    Renier Pretorius avatar
    46 posts
    Member since:
    Apr 2010

    Posted 05 Nov 2015 in reply to Petar Marchev Link to this post

    Hi Petar,

     At first I tried to provide a SeriesBrush property on the CategoryDataPoint but this did not yield anything different. Then I created a DebugConverter

    public class DebugConverter : IValueConverter
    {
        public object Convert(object value, Type targetType,
            object parameter, CultureInfo culture)
        {
            Debugger.Break();
            return value;
        }
     
        public object ConvertBack(object value, Type targetType,
            object parameter, CultureInfo culture)
        {
            Debugger.Break();
            return value;
        }
    }
    And hooked it up

    <Setter Property="DefaultVisualStyle">
        <Setter.Value>
            <Style TargetType="Border">
                <!--<Setter Property="Background" Value="Red"/>-->
                <Setter Property="Background" Value="{Binding SeriesBrush, Converter={StaticResource debugConverter}}"/>
            </Style>
        </Setter.Value>
    </Setter>
    But the code never enters the converter.

     I am no coding guru so rely heavily on our friend Google. Not sure what I am missing.

     

     

     

  9. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 05 Nov 2015 Link to this post

    Hello Renier,

    I think that if you remove the " SeriesBrush, " part from the expression and place a break point in the Convert method, you should be able to debug it. The reason that this code does not work is that the SeriesBrush property search fails, because the data context of the expression is the DataPoint and not your actual business item. You can access the data item via the DataItem property of the data point. So if you were to change the binding a little it should work:
    <Setter Property="Background" Value="{Binding DataItem.SeriesBrush, Converter={StaticResource debugConverter}}"/>

    An alternative to declaring a SeriesBrush property in the business item is to use a ElementName binding or a RelativeSourceBinding, also you can use a chart palette. I hope this information helps.

    Regards,
    Petar Marchev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  10. Renier Pretorius
    Renier Pretorius avatar
    46 posts
    Member since:
    Apr 2010

    Posted 05 Nov 2015 in reply to Petar Marchev Link to this post

    Hi Petar,

    That did the trick thanks. I did previously try the "DataItem.SeriesBrush" bit, but at that point did not have the Brush property on the DataPoint object. When I added the Brush to the DataPoint following your previous feedback, I did not add it again.

    Thanks for the assistance.

    Regards

    Renier

  11. Renier Pretorius
    Renier Pretorius avatar
    46 posts
    Member since:
    Apr 2010

    Posted 05 Nov 2015 in reply to Petar Marchev Link to this post

    Hi Petar,

    Maybe not directly related to the original question, but in my case it is related due to being on the same UserControl. I have two graphs showing related information, some of the series are common to both and some not - purely data driven. Currently I have separate legends for each graph, but due to limited screen real estate I would like to use a single legend which combine the legend items from both and only show the unique items. Is this possible with some sort of converter or other means?

  12. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 06 Nov 2015 Link to this post

    Hello Renier,

    There is no out-of-the-box feature that will allow you to do this automatically. However, you should be able to concat the two legend items collections on your own and remove the repeated legend items in the new collection. The chart has a LegendItems property that holds its legend items. You can attach a CollectionChanged handler for the two charts' collections, create a new collection, and feed this new collection to the RadLegend.

    Regards,
    Petar Marchev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
UI for WPF is Visual Studio 2017 Ready