Styling Series without losing Legend Colors

6 posts, 1 answers
  1. Fabian Gehri
    Fabian Gehri avatar
    10 posts
    Member since:
    Feb 2010

    Posted 05 Oct 2011 Link to this post

    Dear Telerik Team

    We are using the RadChart control to display charts whose structure (e.g. the number of series, their color and the number of categories) is only known at runtime. We are using the MVVM pattern and bind to the SeriesMappings and ItemsSource properties of RadChart. The colors for the series are set via the SeriesDefinition.Appearance.Fill property of the SeriesMappings.

    So far, this works perfectly fine, but now we want to be able to change the colors of individual items in each series. E.g. having a red and a blue series we want the first item of the red series to be orange instead of red, but again these colors are only known at runtime.

    According to this article the SeriesDefinition.Appearance property only allows one color per series. Using the styles property of ChartArea or RadChart or using the Palette Brushes would make all series look the same. So, we came to the conclusion that we need to retemplate the default series style.

    We were able to retemplate the style of the Bar item as in this Demo by binding the Fill property to a Brush property of our custom DataItem object.
    <Style x:Key="CustomBarStyle" TargetType="telerik:Bar">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="telerik:Bar">
                        <Canvas x:Name="PART_MainContainer">
                            <Rectangle x:Name="PART_DefiningGeometry"
                                       Height="{TemplateBinding ItemActualHeight}"
                                       Width="{TemplateBinding ItemActualWidth}"
                                       Fill="{Binding DataItem.Brush}"
                                       Style="{TemplateBinding ItemStyle}" />
                            <Rectangle Height="{TemplateBinding ItemActualHeight}"
                                       Width="{TemplateBinding ItemActualWidth}"
                                       Fill="{StaticResource BarMaskBrush}" />
                            <Canvas.RenderTransform>
                                <ScaleTransform x:Name="PART_AnimationTransform" ScaleY="0" />
                            </Canvas.RenderTransform>
                        </Canvas>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    This only works when the SeriesDefinition.Appearance.Fill property is not set, otherwise the SeriesDefinition.Appearance.Fill property takes precedence over the custom style. The problem with this is that the legend items then show the default colors (i.e. the colors which the series would have when SeriesDefinition.Appearance.Fill is not set).
    To overcome this we tried also to retemplate the style of the ChartLegendItem, but we could not find what we could bind to the Fill property of the ChartLegendItem.

    Also using the CreateItemStyleDelegate of the RadChart as in this help topic did not help us further. In the example, only a predefined brush is set to the ChartLegendItems Fill property, but what we need is to set the colors according to our own color definitions (which are only known at runtime). For this we would need a possibility to get the index of the series which the ChartLegendItem corresponds to.

    Is there any possibility to achieve what we need?

    I guess it is not possible to change something on the precendence of the SeriesDefinition.Appearance over the custom style?

    Is there a way to get the series by the ChartLegendItem? (So far, we are using ChartLegendItem.Label to find the series, but this will fail if multiple series have the same LegendLabel.)

    Or is there even a completely different approach which allows to set colors to individual items without losing the colors in the legend?

    Regards,
    Fabian Gehri

    PS: We are using the Q3 2010 release, but we also tried the Q2 2011 trial version, which did not make a difference.
  2. Answer
    Sia
    Admin
    Sia avatar
    667 posts

    Posted 10 Oct 2011 Link to this post

    Hello Fabian Gehri,

    Thank you for the detailed information about your scenario.
    Two possible options come to my mind:

    1. To generate your legend items manually. More information about this can be found here.
    2. If you need a legend item per series item and you have set the legend display mode to be data point as shown here,  you can bind the ChartLegendItem's fill to the same Brush property, because its DataContext is the corresponding DataPoint:
    <Style x:Key="CustomLegendItem" TargetType="telerik:ChartLegendItem">
        <Setter Property="Padding" Value="5,0,5,0" />
        <Setter Property="Margin" Value="0,3,0,2" />
        <Setter Property="Template" >
            <Setter.Value>
                <ControlTemplate TargetType="telerik:ChartLegendItem">
                    <Grid x:Name="PART_MainContainer" Background="{TemplateBinding Background}"
                        HorizontalAlignment="Stretch" VerticalAlignment="Top">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Path x:Name="PART_LegendItemMarker"
                            Width="16"
                            Height="16"
                            Margin="{TemplateBinding Margin}"
                            StrokeThickness="{TemplateBinding MarkerStrokeThickness}"
                            Style="{TemplateBinding ItemStyle}"
                            Fill="{Binding DataItem.Brush}"
                            Stretch="Fill">
                            <Path.Data>
                                <PathGeometry x:Name="PART_ItemMarkerGeometry" />
                            </Path.Data>
                        </Path>
     
                        <TextBlock x:Name="PART_TextBlock"
                                Grid.Column="1"
                                Padding="{TemplateBinding Padding}"
                                Margin="{TemplateBinding Margin}"
                                Foreground="{TemplateBinding Foreground}"
                                Text="{TemplateBinding Label}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    Please let me know if this helps.
    Kind regards,
    Sia
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. DevCraft banner
  4. Fabian Gehri
    Fabian Gehri avatar
    10 posts
    Member since:
    Feb 2010

    Posted 12 Oct 2011 Link to this post

    Hi Sia,

    thank you very much for your suggestions.

    Legend items per data point is not what we want as there would be too many in most cases. However, generating the legend items manually solved our issue.

    Thanks again,
    Fabian
  5. Bhakti
    Bhakti avatar
    23 posts
    Member since:
    Jan 2011

    Posted 03 Feb 2012 Link to this post

    Hello I have a similar code
     <Style x:Key="CustomLegendItemStyle" TargetType="telerik:ChartLegendItem">
                <Setter Property="Template" >
                    <Setter.Value>
                        <ControlTemplate TargetType="telerik:ChartLegendItem" >
                            <Grid x:Name="PART_MainContainer" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,0,5,0" >
                                <Path x:Name="PART_LegendItemMarker"                                 
                                      Height="20"
                                      Width="80"
                                      Style="{TemplateBinding ItemStyle}"
                                      Stretch="Fill"
                                      >
                                    <Path.Data>
                                        <PathGeometry x:Name="PART_ItemMarkerGeometry" />
                                    </Path.Data>
                                </Path>
                                <CheckBox IsChecked="True"
                                          VerticalAlignment="Center"
                                          Margin="2,0"
                                          Content="{TemplateBinding Label}"
                                          Foreground="{TemplateBinding Foreground}"                                      
                                          BorderThickness="0"
                                          Checked="CheckBox_Checked" Unchecked="CheckBox_Checked"   />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>


    I want to remove the border of the legend items. I have a grid with checkbox and data in each legend item.
  6. Sia
    Admin
    Sia avatar
    667 posts

    Posted 08 Feb 2012 Link to this post

    Hello Bhakti,

    In the original ChartLegendItem template there is a template binding to the exposed MarkerStrokeThickness property, which you need to set as follows:
    <Style x:Key="CustomLegendItemStyle" TargetType="telerik:ChartLegendItem">
        <Setter Property="MarkerStrokeThickness" Value="0" />
        <Setter Property="Template" >
            <Setter.Value>
                <ControlTemplate TargetType="telerik:ChartLegendItem" >
                    <Grid x:Name="PART_MainContainer" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,0,5,0" >
                        <Path x:Name="PART_LegendItemMarker"                                
                                Height="20"
                                Width="80"
                                StrokeThickness="{TemplateBinding MarkerStrokeThickness}"
                                Style="{TemplateBinding ItemStyle}"
                                Stretch="Fill">
                            <Path.Data>
                                <PathGeometry x:Name="PART_ItemMarkerGeometry" />
                            </Path.Data>
                        </Path>
                        <CheckBox IsChecked="True"
                                    VerticalAlignment="Center"
                                    Margin="2,0"
                                    Content="{TemplateBinding Label}"
                                    Foreground="{TemplateBinding Foreground}"                                     
                                    BorderThickness="0" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    If you need to change the marker shape, please set the following style to the ChartLegend:
    <Style x:Key="CustomLegend" TargetType="telerik:ChartLegend">
        <Setter Property="LegendItemMarkerShape" Value="Square" />
    </Style>


    All the best,
    Sia
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
  7. Bhakti
    Bhakti avatar
    23 posts
    Member since:
    Jan 2011

    Posted 08 Feb 2012 Link to this post

    Thank You Sia. It worked!
Back to Top
DevCraft banner