This is a migrated thread and some comments may be shown as answers.

borders around clustered/stacked bars

10 Answers 224 Views
ChartView
This is a migrated thread and some comments may be shown as answers.
Joe
Top achievements
Rank 1
Joe asked on 01 Jul 2014, 07:45 PM
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!

10 Answers, 1 is accepted

Sort by
0
Petar Marchev
Telerik team
answered on 03 Jul 2014, 06:42 AM
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.
 
0
Joe
Top achievements
Rank 1
answered on 03 Jul 2014, 03:13 PM
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!
0
Joe
Top achievements
Rank 1
answered on 03 Jul 2014, 03:17 PM
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>
...
0
Renier Pretorius
Top achievements
Rank 2
Iron
Iron
Iron
answered on 05 Nov 2015, 06:34 AM

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? 

 

 

0
Petar Marchev
Telerik team
answered on 05 Nov 2015, 08:46 AM
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
0
Renier Pretorius
Top achievements
Rank 2
Iron
Iron
Iron
answered on 05 Nov 2015, 09:23 AM

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.

 

 

 

0
Petar Marchev
Telerik team
answered on 05 Nov 2015, 11:12 AM
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
0
Renier Pretorius
Top achievements
Rank 2
Iron
Iron
Iron
answered on 05 Nov 2015, 12:23 PM

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

0
Renier Pretorius
Top achievements
Rank 2
Iron
Iron
Iron
answered on 05 Nov 2015, 12:39 PM

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?

0
Petar Marchev
Telerik team
answered on 06 Nov 2015, 09:04 AM
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
Tags
ChartView
Asked by
Joe
Top achievements
Rank 1
Answers by
Petar Marchev
Telerik team
Joe
Top achievements
Rank 1
Renier Pretorius
Top achievements
Rank 2
Iron
Iron
Iron
Share this question
or