Hello,
I have 2 issues with the attached chart legend:
1) I would like the legend items to be displayed on 2 adjacent columns (see chart legend expected.png). Is that possible?
2) I don't know if you noticed but item legend texts are not perfectly left aligned. Do you have a fix for that?
Best,
Mathias
18 Answers, 1 is accepted
Thank you for writing.
The ChartLegendElement displays the legend items in a StackLayoutElement which can be vertical or horizontal. In order to display the legend items in two columns, you can use two additional vertical StackLayoutElement. Here is a sample code snippet, which result is illustrated on the attached screenshot:
public Form1(){ InitializeComponent(); Random rand = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 8; i++) { LineSeries lineSeries = new LineSeries(); sb = new StringBuilder(); for (int j = 0; j < i + 1; j++) { sb.Append("S0" + i); } lineSeries.LegendTitle = sb.ToString(); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Jan")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Apr")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Jul")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Oct")); this.radChartView1.Series.Add(lineSeries); } this.radChartView1.ShowLegend = true; this.radChartView1.ChartElement.LegendPosition = LegendPosition.Bottom;}class MyChart : RadChartView{ protected override RadChartElement CreateChartElement() { return new MyChartElement(); }}class MyChartElement : RadChartElement{ protected override ChartLegendElement CreateChartLegendElement() { return new MyLegendElement(this); } protected override Type ThemeEffectiveType { get { return typeof(RadChartElement); } }}class MyLegendElement : ChartLegendElement{ StackLayoutElement leftPanel = new StackLayoutElement(); StackLayoutElement rightPanel = new StackLayoutElement(); public MyLegendElement(RadChartElement chartElement) : base(chartElement) { } protected override void CreateChildElements() { base.CreateChildElements(); this.StackElement.Orientation = System.Windows.Forms.Orientation.Horizontal; } protected override void OnLegendInfosCollectionChanged(Telerik.WinControls.Data.NotifyCollectionChangedEventArgs e, bool providerChange) { if (!this.StackElement.Children.Contains(leftPanel)) { this.StackElement.Children.Add(leftPanel); leftPanel.Orientation = System.Windows.Forms.Orientation.Vertical; } if (!this.StackElement.Children.Contains(rightPanel)) { this.StackElement.Children.Add(rightPanel); rightPanel.Orientation = System.Windows.Forms.Orientation.Vertical; } leftPanel.Children.Clear(); rightPanel.Children.Clear(); for (int i = 0; i < this.Provider.LegendInfos.Count; i++) { LegendItemElement element = this.OnVisualItemCreating(this.Provider.LegendInfos[i]); if (i < this.Provider.LegendInfos.Count / 2) { leftPanel.Children.Add(element); } else { rightPanel.Children.Add(element); } } } protected override Type ThemeEffectiveType { get { return typeof(ChartLegendElement); } }}As to the question about text alignment of the items in the LegendElement, I was unable to reproduce it on my end with the specified version 2015.1 331. I have attached my sample project. Could you please have a look into it and specify how it differs from your real setup? Thus, we would be able to investigate the precise case and assist you further. Thank you in advance.
I am looking forward to your reply.
Dess
Telerik
See What's Next in App Development. Register for TelerikNEXT.
BUEN DÍA ESTOY REALIZANDO UNAS GRAFICAS, TENGO UNA DUDA, CON EL TIPO DE SERIE TYPE Line LA LEGENDA SE VISUALIZA, PERO CON EL TYPE ScatterLine LA S LEYENDAS NO SE VISUALIZAN, E VISTO EL docs.telerik Y LOS EJEMPLOS MOSTRADOS NO TIENEN VISUALIZADOS LA LEYENDA, ¿HAY ALGUNA FORMA QUE SE VISUALICEN?
ADJUNTO MI PANTALLA
Thank you for writing back.
I would like to note that the official language for communication in the Telerik forums is English. If you have any questions related to the Telerik UI for WinForms product, feel free to use the appropriate language and the community will gladly assist you.
Thank you for your understanding.
Regards,
Dess
Progress Telerik
Hello,
I am creating stacked bar series using Telerik Win forms in my server side in Vb. I am not able to display legends at the bottom in multiple lines. I am attaching both actual and expended chart.
Since Q1 2015 when there are many items in the chart legend a scroll bar will appear so users can scroll through the items. The legend items are not wrapped indeed
I have prepared a sample code snippet which achieves a similar custom scenario. The obtained result is illustrated in the below screenshot:
Sub New() InitializeComponent() Dim rand As New Random Dim list As New List(Of LineSeries) For index = 1 To 15 Dim ls As New LineSeries ls.LegendTitle = "Series " & index list.Add(ls) Next For index = 1 To 100 For Each s As LineSeries In list s.DataPoints.Add(New CategoricalDataPoint(index, rand.Next(0, rand.Next(5, 20)))) Next Next Me.RadChartView1.Series.AddRange(list.ToArray()) Me.RadChartView1.ShowLegend = True Me.RadChartView1.ChartElement.LegendPosition = LegendPosition.Bottom End SubFriend Class MyChartInherits RadChartView Protected Overrides Function CreateChartElement() As RadChartElement Return New MyChartElement() End FunctionEnd ClassFriend Class MyChartElementInherits RadChartElement Protected Overrides Function CreateChartLegendElement() As ChartLegendElement Return New MyLegendElement(Me) End Function Protected Overrides ReadOnly Property ThemeEffectiveType() As Type Get Return GetType(RadChartElement) End Get End PropertyEnd ClassFriend Class MyLegendElementInherits ChartLegendElement Private panel As RadListViewElement Public Sub New(chartElement As RadChartElement) MyBase.New(chartElement) End Sub Protected Overrides Sub OnLegendInfosCollectionChanged(e As Telerik.WinControls.Data.NotifyCollectionChangedEventArgs, providerChange As Boolean) MyBase.OnLegendInfosCollectionChanged(e, providerChange) If e.Action = Telerik.WinControls.Data.NotifyCollectionChangedAction.Add Then Dim li As LegendItem = TryCast(e.NewItems(0), LegendItem) panel.Items.Add(li.Title) End If End Sub Protected Overrides Sub CreateChildElements() MyBase.CreateChildElements() panel = New RadListViewElement() panel.StretchHorizontally = True panel.StretchVertically = False panel.ViewType = ListViewType.IconsView panel.ItemSize = New Drawing.Size(100, 20) panel.ShouldHandleMouseInput = True panel.NotifyParentOnMouseInput = False panel.MaxSize = New Drawing.Size(500, 100) Me.StackElement.Visibility = Telerik.WinControls.ElementVisibility.Collapsed Me.Children.Add(panel) End Sub Protected Overrides ReadOnly Property ThemeEffectiveType() As Type Get Return GetType(ChartLegendElement) End Get End PropertyEnd ClassNote that this is just a sample approach and it may not handle all possible cases. Feel free to modify it in a way which suits your requirement best.
I hope this information helps. If you have any additional questions, please let me know.
Dess
Progress Telerik
Hi Dess,
Thank you for your reply. I am still getting the scroll in my chart.
Regards,
Manasa
It is normal to obtain a scrollbar if the RadListViewElement which hosts the legend items doesn't fit the available space below the chart. You can specify the MinSize property to a specific size that fits all items in the CreateChildElements method. However, if you shrink the chart and RadListViewElement respectively, the scrollbars won't be shown and the items will be clipped.
I hope this information helps. If you have any additional questions, please let me know.
Dess
Progress Telerik
Hi Dess,
I am creating chart in server side and exporting it as an image. Below is my code. I am using MyChart which inherits Telerik.WinControls.UI.RadChartView.
Dim radChartView = New MyChart
radChartView.ShowLegend = True
radChartView.ShowTitle = True
radChartView.Title = "Annual education cost analysis"
radChartView.ChartElement.TitleElement.TextAlignment = ContentAlignment.TopCenter
radChartView.ChartElement.LegendElement.TitleElement.Font = New Font(FontType, 15.0F, FontStyle.Regular)
radChartView.ChartElement.LegendElement.TitlePosition = Telerik.WinControls.UI.TitlePosition.Top
radChartView.ChartElement.LegendElement.TitleElement.ForeColor = Color.FromArgb(51, 51, 51)
radChartView.ChartElement.LegendPosition = Telerik.WinControls.UI.LegendPosition.Float
radChartView.ChartElement.LegendElement.StackElement.Orientation = System.Windows.Forms.Orientation.Horizontal
radChartView.ChartElement.LegendOffset = New Point(100, radChartView.Size.Height + 10)
radChartView.Area.View.Palette = CustomTelerikPalette
radChartView.Size = New System.Drawing.Size(600, 400)
Dim annualContributionLineSeries = New Telerik.WinControls.UI.LineSeries()
annualContributionLineSeries.PointSize = New SizeF(10, 10)
annualContributionLineSeries.LegendTitle = "Annual Contribution Amount"
annualContributionLineSeries.BorderWidth = 2
annualContributionLineSeries.DataSource = chartData.AnnualContributionAmount
annualContributionLineSeries.ValueMember = "Balance"
annualContributionLineSeries.CategoryMember = "FinanceYear"
annualContributionLineSeries.BackColor = Color.Red
radChartView.Series.Add(annualContributionLineSeries)
Dim chartTitle = LegendTitle(calculatorOutput)
Dim barSeriesList As New List(Of Telerik.WinControls.UI.BarSeries)
For index = 0 To calculatorOutput.CostList.individualCost.Count - 1
Dim barSeries = New Telerik.WinControls.UI.BarSeries
barSeries.LegendTitle = chartTitle(index)
barSeries.CombineMode = Telerik.Charting.ChartSeriesCombineMode.Stack
barSeriesList.Add(barSeries)
Next
Dim startYear = chartData.AnnualContributionAmount(0).FinanceYear
Dim eachChildren = 0
For Each item In barSeriesList
For i = 0 To calculatorOutput.CostList.individualCost(0).Count - 1
item.DataPoints.Add(New Telerik.Charting.CategoricalDataPoint(calculatorOutput.CostList.individualCost(eachChildren)(i), startYear + i))
Next
eachChildren += 1
Next
radChartView.Series.AddRange(barSeriesList.ToArray())
Dim yAxis As Telerik.WinControls.UI.LinearAxis = TryCast(radChartView.Axes(1), Telerik.WinControls.UI.LinearAxis)
yAxis.LabelFormat = "{0:c0}"
Dim xAxis As Telerik.WinControls.UI.CategoricalAxis = TryCast(radChartView.Axes(0), Telerik.WinControls.UI.CategoricalAxis)
xAxis.LabelFitMode = Telerik.Charting.AxisLabelFitMode.Rotate
xAxis.LabelRotationAngle = 90
Dim ms = New MemoryStream()
radChartView.ExportToImage(ms, radChartView.Size, System.Drawing.Imaging.ImageFormat.Jpeg)
ms.Seek(0, SeekOrigin.Begin)
Return ms
End Function
I am attaching my output which is an image.
Hi Dess,
Thank you for your help. I am able to display legends in 2 lines. But the marker is not visible in the legend of chart. I have uploaded both actual and expected legend markers.
Regards,
Manasa
You can show the check-boxes in the RadListViewElement which is used for the legend items and color the check-boxes n the color of the series. Here is demonstrates a sample code snippet which result is illustrated in the below screenshot:
Friend Class MyLegendElementInherits ChartLegendElement Private panel As RadListViewElement Public Sub New(chartElement As RadChartElement) MyBase.New(chartElement) End Sub Protected Overrides Sub OnLegendInfosCollectionChanged(e As Telerik.WinControls.Data.NotifyCollectionChangedEventArgs, providerChange As Boolean) MyBase.OnLegendInfosCollectionChanged(e, providerChange) If e.Action = Telerik.WinControls.Data.NotifyCollectionChangedAction.Add Then Dim li As LegendItem = TryCast(e.NewItems(0), LegendItem) panel.Items.Add(li.Title) panel.Items.Last().Tag = li.Element End If panel.SelectedIndex = -1 End Sub Protected Overrides Sub CreateChildElements() MyBase.CreateChildElements() panel = New RadListViewElement() AddHandler panel.VisualItemFormatting, AddressOf ListView_VisualItemFormatting panel.ShowCheckBoxes = True panel.StretchHorizontally = True panel.StretchVertically = False panel.ViewType = ListViewType.IconsView panel.ItemSize = New Drawing.Size(100, 20) panel.ShouldHandleMouseInput = True panel.NotifyParentOnMouseInput = False panel.MaxSize = New Drawing.Size(500, 100) panel.MinSize = New Drawing.Size(420, 100) Me.StackElement.Visibility = Telerik.WinControls.ElementVisibility.Collapsed Me.Children.Add(panel) End Sub Protected Overrides ReadOnly Property ThemeEffectiveType() As Type Get Return GetType(ChartLegendElement) End Get End Property Private Sub ListView_VisualItemFormatting(sender As Object, e As ListViewVisualItemEventArgs) Dim checkBox As ListViewItemCheckbox = TryCast(e.VisualItem.ToggleElement, ListViewItemCheckbox) If checkBox IsNot Nothing Then e.VisualItem.ToggleElement.ShouldHandleMouseInput = False e.VisualItem.ToggleElement.NotifyParentOnMouseInput = False checkBox.CheckMarkPrimitive.Fill.BackColor = DirectCast(e.VisualItem.Data.Tag, LineSeries).BorderColor checkBox.CheckMarkPrimitive.Fill.GradientStyle = Telerik.WinControls.GradientStyles.Solid checkBox.CheckMarkPrimitive.Border.Visibility = Telerik.WinControls.ElementVisibility.Collapsed End If End SubEnd ClassRegards,
Dess
Progress Telerik
Hello Dess,
Thank you very much for the solution, it worked. I have a last question, I observed when I am adding bar and line series in a chart, the line series point is not in the middle of the bar. I am attaching the screenshots and have highlighted in yellow. I am also attaching stacked bar chart, size of bar is bigger and is in between the marker ticks. I have used horizontalAxis.PlotMode = Telerik.Charting.AxisPlotMode.OnTicksPadded
Regards,
Manasa
In order to place the points of the LineSeries you should set the LineSeries.CombineMode property to ChartSeriesCombineMode.None:
I hope this information helps. If you have any additional questions, please let me know.
Dess
Progress Telerik
Hello Dess,
Thank you very much for the solution.
Regards,
Manasa
Hello Dess,
I am trying to display the series title like a label in the chart. Could you please help me with that?
I am attaching my expected chart.
Regards,
Mansi
Grid line annotations may be suitable for achieving your goal. Please refer to the following help article: https://docs.telerik.com/devtools/winforms/chartview/features/annotations/grid-line
Should you have further questions please let me know.
Regards,
Dess
Progress Telerik
If you want to use the drill-down functionality in RadChartView, it is necessary to extend the previously provided code snippet and create a custom ChartWrapper. Then, override its DrillDown and DrillToIndex methods in order to reset the legend element and fill the left/right panels with the respective items.
public Form1(){ InitializeComponent(); Random rand = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 8; i++) { LineSeries lineSeries = new LineSeries(); sb = new StringBuilder(); for (int j = 0; j < i + 1; j++) { sb.Append("S0" + i); } lineSeries.PointSize = new SizeF(10, 10); lineSeries.LegendTitle = sb.ToString(); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Jan")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Apr")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Jul")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Oct")); this.radChartView1.Series.Add(lineSeries); } this.radChartView1.ShowLegend = true; this.radChartView1.ChartElement.LegendPosition = LegendPosition.Bottom; DrillDownController drillControler = new DrillDownController(); this.radChartView1.Controllers.Add(drillControler); radChartView1.Views.AddNew("Revenue by Month"); this.radChartView1.Drill += RadChartView1_Drill; this.radChartView1.ShowDrillNavigation = true;}private void RadChartView1_Drill(object sender, DrillEventArgs e){ e.View.Series.Clear(); e.View.Axes.Clear(); Random rand = new Random(); switch (e.Level) { case 0: for (int i = 0; i < 8; i++) { LineSeries lineSeries = new LineSeries(); StringBuilder sb = new StringBuilder(); sb = new StringBuilder(); for (int j = 0; j < i + 1; j++) { sb.Append("S0" + i); } lineSeries.PointSize = new SizeF(10, 10); lineSeries.LegendTitle = sb.ToString(); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Jan")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Apr")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Jul")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Oct")); e.View.Series.Add(lineSeries); } break; case 1: if (e.SelectedPoint != null) for (int i = 0; i < 8; i++) { LineSeries lineSeries = new LineSeries(); StringBuilder sb = new StringBuilder(); sb = new StringBuilder(); for (int j = 0; j < i + 1; j++) { sb.Append("S0" + i + DateTime.Now.ToLongTimeString()); } lineSeries.PointSize = new SizeF(10, 10); lineSeries.LegendTitle = sb.ToString(); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Jan")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Apr")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Jul")); lineSeries.DataPoints.Add(new CategoricalDataPoint(rand.Next(-50, 50), "Oct")); e.View.Series.Add(lineSeries); } break; } }class MyChart : RadChartView{ protected override RadChartElement CreateChartElement() { return new MyChartElement(); }}class MyChartElement : RadChartElement{ protected override ChartLegendElement CreateChartLegendElement() { return new MyLegendElement(this); } protected override ChartWrapper CreateChartWrapperElement() { return new CustomChartWrapper(); } protected override Type ThemeEffectiveType { get { return typeof(RadChartElement); } }}public class CustomChartWrapper : ChartWrapper{ public override bool DrillDown(DataPoint point) { bool result = base.DrillDown(point); ((MyLegendElement)((RadChartView)this.ElementTree.Control).ChartElement.LegendElement).ResetLegend(); return result; } public override bool DrillUp() { bool result = base.DrillUp(); ((MyLegendElement)((RadChartView)this.ElementTree.Control).ChartElement.LegendElement).ResetLegend(); return result; } public override bool DrillToIndex(int viewIndex) { bool result= base.DrillToIndex(viewIndex); ((MyLegendElement)((RadChartView)this.ElementTree.Control).ChartElement.LegendElement).ResetLegend(); return result; }}class MyLegendElement : ChartLegendElement{ StackLayoutElement leftPanel = new StackLayoutElement(); StackLayoutElement rightPanel = new StackLayoutElement(); public MyLegendElement(RadChartElement chartElement) : base(chartElement) { } protected override void CreateChildElements() { base.CreateChildElements(); this.StackElement.Orientation = System.Windows.Forms.Orientation.Horizontal; } protected override void OnLegendInfosCollectionChanged(Telerik.WinControls.Data.NotifyCollectionChangedEventArgs e, bool providerChange) { ResetLegend(); } public void ResetLegend() { this.StackElement.Children.Clear(); if (!this.StackElement.Children.Contains(leftPanel)) { this.StackElement.Children.Add(leftPanel); leftPanel.Orientation = System.Windows.Forms.Orientation.Vertical; } if (!this.StackElement.Children.Contains(rightPanel)) { this.StackElement.Children.Add(rightPanel); rightPanel.Orientation = System.Windows.Forms.Orientation.Vertical; } leftPanel.Children.Clear(); rightPanel.Children.Clear(); for (int i = 0; i < this.Provider.LegendInfos.Count; i++) { LegendItemElement element = this.OnVisualItemCreating(this.Provider.LegendInfos[i]); if (i < this.Provider.LegendInfos.Count / 2) { leftPanel.Children.Add(element); } else { rightPanel.Children.Add(element); } } } protected override Type ThemeEffectiveType { get { return typeof(ChartLegendElement); } }}I hope this information helps.
Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik
