Skip to main content Skip to footer

Group Legend Elements in C1Chart WPF

Grouping is one of the features which definitely makes data more readable/presentable to end users and also helps in quick analysis in some scenarios. This is yet another post which will highlight 'grouping' feature but in combination with a different control : C1ChartLegend (or an ItemsControl). Ok, before we start on how to go about achieving this with chart legend, lets take a quick look on how our the chart will actually look after grouping legend items. The above chart shows GDP of countries with countries grouped on the basis of the continents. Cool :) The idea here is to create a custom chart legend (inherit default chart legend) along with custom chart LegendItems (with same properties). The custom LegendItem will also have a property to group the items:-


public class MyLegendItem  
 {  
   public object Item { get; set; }  
   public string Label { get; set; }  
   public Shape Line { get; set; }  
   public Shape Symbol { get; set; }  
   public string Group  
   {  
    get  
      {  
       // use the 'Tag' property on series to group the items  
       return (this.Item as DataSeries).Tag.ToString();  
      }  
   }  
 }  

The custom legend will be something like this:-



public class MyChartLegend : C1ChartLegend  
  {  
    public MyChartLegend()  
    {  
     this.Template = null;  
     this.Loaded += (s, e) =>  
      {  
       var chart = this.FindParent<C1Chart>()  as C1Chart;  
       var list = new List<MyLegendItem>();  
       foreach (LegendItem li in chart.LegendItems)  
        {  
         list.Add(new MyLegendItem() { Line = li.Line, Symbol = li.Symbol, Label = li.Label, Item = li.Item });  
        }  
    var lcv = new ListCollectionView(list);  
    lcv.GroupDescriptions.Add(new PropertyGroupDescription("Group"));  
    this.ItemsSource = lcv;  
    };  
   }  
 }  


The above code just changes the legend's actual ItemsSource and groups the CollectionView using 'Group' property. The xaml will look like below:-


<local:MyChartLegend Background="{x:Null}" DockPanel.Dock="Right" x:Name="legend" VerticalAlignment="Center">  
   <local:MyChartLegend.Template>  
   <ControlTemplate TargetType="ItemsControl">  
    <Border Name="bdr">  
    <ScrollViewer Name="sv" VerticalScrollBarVisibility="Visible">  
     <ItemsPresenter/>  
   </ScrollViewer>  
   </Border>  
  </ControlTemplate>  
  </local:MyChartLegend.Template>  
  <local:MyChartLegend.GroupStyle>  
    <GroupStyle>  
    <GroupStyle.ContainerStyle>  
    <Style TargetType="{x:Type GroupItem}">  
    <Setter Property="Template">  
    <Setter.Value>  
    <ControlTemplate TargetType="{x:Type GroupItem}">  
    <Expander IsExpanded="False" >  
    <Expander.Header>  
    <DockPanel>  
    <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100"/>  
   </DockPanel>  
  </Expander.Header>  
  <Expander.Content>  
   <ItemsPresenter Margin="25,0,0,0" />  
  </Expander.Content>  
   </Expander>  
   </ControlTemplate>  
  </Setter.Value>  
  </Setter>  
  </Style>  
 </GroupStyle.ContainerStyle>  
 </GroupStyle>  
 </local:MyChartLegend.GroupStyle>  
 <local:MyChartLegend.ItemTemplate>  
   <DataTemplate DataType="{x:Type local:MyLegendItem}">  
   <StackPanel Orientation="Horizontal">  
   <Canvas Width="24" Height="24">  
   <ContentControl Canvas.Top="2" Content="{Binding Path=Line}" Width="24" Height="20"/>  
   <ContentControl Canvas.Left="5" Canvas.Top="5" Content="{Binding Path=Symbol}" Width="14" Height="14"/>  
   </Canvas>  
   <TextBlock Margin="2"  
   Text="{Binding Path=Label}"  
   VerticalAlignment="Center"/>  
   </StackPanel>  
   </DataTemplate>  
   </local:MyChartLegend.ItemTemplate>  
 </local:MyChartLegend>  

This is it. Chart here can be populated using the data given below :-


public static class Data  
{  
 public static List<GDP> GetData()  
 {  
    var list = new List<GDP>();  
    list.Add(new GDP() { Country = "USA", Continent = "North America", Value = 14.9, Rank = 1 });  
    list.Add(new GDP() { Country = "China", Continent = "Asia", Value = 7.2, Rank = 2 });  
    list.Add(new GDP() { Country = "Japan", Continent = "Asia", Value = 5.8, Rank = 3 });  
    list.Add(new GDP() { Country = "Germany", Continent = "Europe", Value = 3.6, Rank = 4 });  
    list.Add(new GDP() { Country = "France", Continent = "Europe", Value = 2.7, Rank = 5 });  
    list.Add(new GDP() { Country = "Brazil", Continent = "South America", Value = 2.4, Rank = 6 });  
    list.Add(new GDP() { Country = "United Kingdom", Continent = "Europe", Value = 2.4, Rank = 7 });  
    list.Add(new GDP() { Country = "Italy", Continent = "Europe", Value = 2.1, Rank = 8 });  
    list.Add(new GDP() { Country = "India", Continent = "Asia", Value = 1.8, Rank = 9 });  
    list.Add(new GDP() { Country = "Russia", Continent = "Europe", Value = 1.8, Rank = 10 });  
    list.Add(new GDP() { Country = "Canada", Continent = "North America", Value = 1.7, Rank = 11 });  
    list.Add(new GDP() { Country = "Australia", Continent = "Australia", Value = 1.5, Rank = 12 });  
    list.Add(new GDP() { Country = "Spain", Continent = "Europe", Value = 1.4, Rank = 13 });  
    list.Add(new GDP() { Country = "Mexico", Continent = "North America", Value = 1.1, Rank = 14 });  
    list.Add(new GDP() { Country = "South Korea", Continent = "Asia", Value = 1.1, Rank = 15 });  

    return list;  
  }  
}  

Please download the attached sample for complete implementation. Download Sample

MESCIUS inc.

comments powered by Disqus