3D Charts will be a nice addition to the WinForms suite
RadChartView should visualize the pan and zoom state of a view through a scroll bar
When setting the border color of the axis the labels are showing a border with the same color. The color is inherited from the axis element. One should be able to easily disable this, or it should not happen. How to reproduce: public partial class RadForm1 : Telerik.WinControls.UI.RadForm { LineSeries lineSeries; public RadForm1() { InitializeComponent(); this.lineSeries = new LineSeries(); this.lineSeries.DataPoints.Add(new CategoricalDataPoint(20, "Jan")); this.lineSeries.DataPoints.Add(new CategoricalDataPoint(22, "Apr")); this.lineSeries.DataPoints.Add(new CategoricalDataPoint(25, "Jul")); this.lineSeries.DataPoints.Add(new CategoricalDataPoint(19, "Oct")); this.radChartView1.Series.Add(this.lineSeries); this.lineSeries.HorizontalAxis.BorderColor = Color.Green; this.lineSeries.VerticalAxis.BorderColor = Color.Blue; } } Workaround: iterate each of the axis labels and set their border color to Transparent public partial class RadForm1 : Telerik.WinControls.UI.RadForm { LineSeries lineSeries; public RadForm1() { InitializeComponent(); this.lineSeries = new LineSeries(); this.lineSeries.DataPoints.Add(new CategoricalDataPoint(20, "Jan")); this.lineSeries.DataPoints.Add(new CategoricalDataPoint(22, "Apr")); this.lineSeries.DataPoints.Add(new CategoricalDataPoint(25, "Jul")); this.lineSeries.DataPoints.Add(new CategoricalDataPoint(19, "Oct")); this.radChartView1.Series.Add(this.lineSeries); this.lineSeries.HorizontalAxis.BorderColor = Color.Green; this.lineSeries.VerticalAxis.BorderColor = Color.Blue; } protected override void OnShown(EventArgs e) { base.OnShown(e); foreach (var item in this.lineSeries.VerticalAxis.Children) { AxisLabelElement label = item as AxisLabelElement; if (label != null) { label.BorderColor = Color.Transparent; } } foreach (var item in this.lineSeries.HorizontalAxis.Children) { AxisLabelElement label = item as AxisLabelElement; if (label != null) { label.BorderColor = Color.Transparent; } } } }
Hello Telerik Support,
after taking my first steps with RangeSelector and ChartView controls I found an issue with a simple bar chart. The length of some bars in the chart of the RangeSelector doesn't match with the bars in the ChartView. The relation is wrong.I provided a screenshot and marked the bars. I could provide a sample application, but I can't attach a zip file, so here's the code of the main form:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Linq;
using
System.Text;
using
System.Windows.Forms;
using
Telerik.WinControls;
using
Telerik.WinControls.UI;
namespace
TelerikChartView
{
public
partial
class
MainForm : Telerik.WinControls.UI.RadForm
{
private
List<Kapazitaetspunkt> _BackListPunkte;
private
BindingList<Kapazitaetspunkt> Punkte;
public
MainForm()
{
InitializeComponent();
}
private
void
MainForm_Load(
object
sender, EventArgs e)
{
_BackListPunkte =
new
List<Kapazitaetspunkt>();
Punkte =
new
BindingList<Kapazitaetspunkt>(_BackListPunkte);
//Punkte = new BindingList<Kapazitaetspunkt>();
rngTimeSelector.AssociatedControl = cvChart;
rngTimeSelector.RangeSelectorElement.ScrollSelectorElement.Visibility = ElementVisibility.Collapsed;
BarSeries bars =
new
BarSeries();
bars.DataSource = Punkte;
bars.ValueMember = nameof(Kapazitaetspunkt.Percentage);
bars.CategoryMember = nameof(Kapazitaetspunkt.Date);
cvChart.Series.Add(bars);
}
private
void
GenerateTestData(
int
addMonths = 0)
{
Punkte.Clear();
const
int
count = 25;
const
int
step = 4;
var von = DateTime.Today.AddMonths(addMonths);
var bis = von.AddDays(count);
double
percentage = 0;
//_BackListPunkte.Add(new Kapazitaetspunkt(von.AddDays(-1), null));
Punkte.Add(
new
Kapazitaetspunkt(von.AddDays(-1),
null
));
while
(von < bis)
{
//_BackListPunkte.Add(new Kapazitaetspunkt(von, percentage));
Punkte.Add(
new
Kapazitaetspunkt(von, percentage));
percentage += step;
von = von.AddDays(1);
}
//_BackListPunkte.Add(new Kapazitaetspunkt(von.AddDays(1), null));
Punkte.Add(
new
Kapazitaetspunkt(von.AddDays(1),
null
));
}
private
void
btnGenerateData_Click(
object
sender, EventArgs e)
{
GenerateTestData();
rngTimeSelector.RangeSelectorElement.InitializeElements();
rngTimeSelector.RangeSelectorElement.ResetLayout(
true
);
}
private
void
btnGenerateData2_Click(
object
sender, EventArgs e)
{
GenerateTestData(2);
rngTimeSelector.RangeSelectorElement.InitializeElements();
rngTimeSelector.RangeSelectorElement.ResetLayout(
true
);
}
private
void
rngTimeSelector_ScaleInitializing(
object
sender, ScaleInitializingEventArgs e)
{
e.Cancel =
true
;
}
}
public
class
Kapazitaetspunkt : INotifyPropertyChanged
{
private
DateTime _Date;
public
DateTime Date
{
get
=> _Date;
set
{
if
(value != Date)
{
_Date = value;
OnPropertyChanged();
}
}
}
public
double
? _Percentage;
public
double
? Percentage
{
get
=> _Percentage;
set
{
if
(value != Percentage)
{
_Percentage = value;
OnPropertyChanged();
}
}
}
public
Kapazitaetspunkt(DateTime date,
double
? percentage)
{
Date = date;
Percentage = percentage;
}
public
event
PropertyChangedEventHandler PropertyChanged;
protected
virtual
void
OnPropertyChanged([CallerMemberName]
string
propertyName =
null
)
{
PropertyChanged?.Invoke(
this
,
new
PropertyChangedEventArgs(propertyName));
}
}
}
Regards,
Stephan
The new functionality should allow a display similar to the one in the WPF pie series: http://docs.telerik.com/devtools/wpf/controls/radchartview/features/labels/smart-labels#using-smart-labels-in-radpiechart
Note: when you apply a palette the series doesn't have hover and selection indication.
How to reproduce: create a drill down chart with different area types on the different levels. The issue seems to be related to some series not implementing the ILegendInfoProvider interface. Workaround: A similar result as having a drill-down chart with series having different area types can be achieved manually using the ChartSelectionController. Please check the attached project and video file.
It would be great to be able to generate Box Plot graphics, both in the RadCharView control and in the Report.
When combining scalebreaks and series stacking, the rendered chart does not match the data. See attached solution: The bar of the category "1/2016" has a length of 105 (as indicated by the tooltips) -- but the corresponding axis labeling shows a value of 37. The scalebreak is off too (probably matching the wrong axis).
To reproduce: public Form1() { InitializeComponent(); this.radChartView1.AreaType = ChartAreaType.Polar; Random rand = new Random(); for (int i = 0; i < 80; i++) { RadarLineSeries s = new RadarLineSeries(); s.ShowLabels = true; for (int j = 0; j < 8; j++) { s.DataPoints.Add(new CategoricalDataPoint(rand.Next(1, 100), "X" + j)); } this.radChartView1.Series.Add(s); } this.radChartView1.ShowSmartLabels = true; }
To reproduce: public Form1() { InitializeComponent(); Random rand = new Random(); for (int i = 0; i < 3; i++) { LineSeries lineSeries = new LineSeries(); 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; ((LineSeries)this.radChartView1.Series[0]).LegendTitle = "S&P 500"; ((LineSeries)this.radChartView1.Series[1]).LegendTitle = "MSCI Emerging Markets TR Index"; ((LineSeries)this.radChartView1.Series[2]).LegendTitle = "Great ETF"; } Workaround: Font f = new Font("Times New Roman", 10f, FontStyle.Regular); private void Form1_Load(object sender, EventArgs e) { foreach (LegendItemElement item in this.radChartView1.ChartElement.LegendElement.StackElement.Children) { item.Font = f; } }
To reproduce: - Subscribe to the SelectedPointChanged event and show a dialog in it. - Start the chart and zoom in. Select a point, close the dialog and select a point again. Workaround: class MyChartSelectionController : ChartSelectionController { protected override ActionResult OnMouseDown(MouseEventArgs e) { //return base.OnMouseDown(e); return Controller.Empty; } protected override ActionResult OnMouseUp(MouseEventArgs e) { if (!this.AllowSelect || this.SelectionMode == ChartSelectionMode.None) { return base.OnMouseUp(e); } DataPoint oldDataPoint = SelectedPoint; DataPoint newDataPoint = null; ChartSeries oldSeries = SelectedSeries; ChartSeries newSeries = null; DataPoint point = null; foreach (ChartSeries series in this.Area.Series) { point = series.HitTest(e.X, e.Y); if (point != null) { newDataPoint = point; newSeries = series; break; } } if (point == null) { return base.OnMouseUp(e); } ChartViewSelectedPointChangingEventArgs cancelArgs = new ChartViewSelectedPointChangingEventArgs(oldDataPoint, newDataPoint, oldSeries, newSeries, this.SelectionMode); OnSelectedPointChanging(cancelArgs); if (cancelArgs.Cancel == true) { return base.OnMouseUp(e); } if (oldDataPoint == newDataPoint) { oldDataPoint.IsSelected = !oldDataPoint.IsSelected; newDataPoint = null; SelectedPoint = null; } else { if (this.SelectionMode == ChartSelectionMode.SingleDataPoint && oldDataPoint != null) { oldDataPoint.IsSelected = false; } this.SelectedPoint = newDataPoint; this.SelectedPoint.IsSelected = !SelectedPoint.IsSelected; } ChartViewSelectedPointChangedEventArgs changedArgs = new ChartViewSelectedPointChangedEventArgs(oldDataPoint, newDataPoint, oldSeries, newSeries, this.SelectionMode); OnSelectedPointChanged(changedArgs); return base.OnMouseUp(e); } }
Workaround: use the ChartTrackerballController.TextNeeded event.
To reproduce: BarSeries barSeries = new BarSeries("Performance", "RepresentativeName"); barSeries.Name = "Q1"; barSeries.CombineMode = ChartSeriesCombineMode.Stack; barSeries.DataPoints.Add(new CategoricalDataPoint(177, "Harley")); barSeries.DataPoints.Add(new CategoricalDataPoint(128, "White")); barSeries.DataPoints.Add(new CategoricalDataPoint(143, "Smith")); barSeries.DataPoints.Add(new CategoricalDataPoint(111, "Jones")); barSeries.DataPoints.Add(new CategoricalDataPoint(118, "Marshall")); this.radChartView1.Series.Add(barSeries); BarSeries barSeries2 = new BarSeries("Performance", "RepresentativeName"); barSeries2.Name = "Q2"; barSeries2.CombineMode = ChartSeriesCombineMode.Stack; barSeries2.DataPoints.Add(new CategoricalDataPoint(153, "Harley")); barSeries2.DataPoints.Add(new CategoricalDataPoint(141, "White")); barSeries2.DataPoints.Add(new CategoricalDataPoint(130, "Smith")); barSeries2.DataPoints.Add(new CategoricalDataPoint(88, "Jones")); barSeries2.DataPoints.Add(new CategoricalDataPoint(109, "Marshall")); this.radChartView1.Series.Add(barSeries2); BarSeries barSeries3 = new BarSeries("Performance", "RepresentativeName"); barSeries3.Name = "Q3"; barSeries3.CombineMode = ChartSeriesCombineMode.Stack; barSeries3.DataPoints.Add(new CategoricalDataPoint(153, "Harley")); barSeries3.DataPoints.Add(new CategoricalDataPoint(141, "White")); barSeries3.DataPoints.Add(new CategoricalDataPoint(130, "Smith")); barSeries3.DataPoints.Add(new CategoricalDataPoint(88, "Jones")); barSeries3.DataPoints.Add(new CategoricalDataPoint(109, "Marshall")); this.radChartView1.Series.Add(barSeries3); this.radChartView1.ShowTrackBall = true; Note: the trackball labels should be displayed in the order the series are displayed in the chart view. Workaround: private void ChartTrackballController_TextNeeded(object sender, TextNeededEventArgs e) { string pattern = " \\d+.?\\d* "; StringBuilder sb = new StringBuilder("<html>"); List<DataPointInfo> points = new List<DataPointInfo>(); foreach (DataPointInfo dp in e.Points) { points.Add(dp); } points.Reverse(); foreach (DataPointInfo dp in points) { Color pointColor = this.GetColorForDataPoint(dp.Series, dp.DataPoint); string color = string.Format("{0},{1},{2},{3}", pointColor.A, pointColor.R, pointColor.G, pointColor.B); sb.AppendFormat("<color={0}>{1}", color, string.Format("{0} {1}", dp.Series.Name, ((CategoricalDataPoint)dp.DataPoint).Value)); sb.AppendLine(); } e.Text = sb.ToString(); } protected virtual Color GetColorForDataPoint(ChartSeries series, DataPoint point) { if (series is IndicatorBase) { return series.BorderColor; } foreach (UIChartElement element in series.Children) { DataPointElement pointElement = element as DataPointElement; if (pointElement != null) { if (pointElement.DataPoint.Equals(point)) { if (pointElement.BackColor.A > 0) { return pointElement.BackColor; } else { return pointElement.BorderColor; } } } } return Color.Black; }
The event should not be triggered when moving the mouse over the same data point, as we already asked for data for it. We can cache it and reuse it.
To reproduce: - Set the position like this: this.radChartView1.ChartElement.LegendElement.Alignment = ContentAlignment.TopCenter; - Export the chart to an image, the position is not the same as in the application. Workaround: - Set the position manually: this.radChartView1.ChartElement.LegendPosition = LegendPosition.Float; this.radChartView1.ChartElement.LegendOffset = new Point(400, 0);
How to reproduce: Public Class Form1 Sub New() InitializeComponent() Dim barSeries As New Telerik.WinControls.UI.BarSeries("Performance", "RepresentativeName") barSeries.Name = "Q1" barSeries.LegendTitle = "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "Leg barSeries.DataPoints.Add(New CategoricalDataPoint(177, "Harley")) barSeries.DataPoints.Add(New CategoricalDataPoint(128, "White")) barSeries.DataPoints.Add(New CategoricalDataPoint(143, "Smith")) barSeries.DataPoints.Add(New CategoricalDataPoint(111, "Jones")) barSeries.DataPoints.Add(New CategoricalDataPoint(118, "Marshall")) Me.RadChartView1.Series.Add(barSeries) Dim barSeries2 As New Telerik.WinControls.UI.BarSeries("Performance", "RepresentativeName") barSeries2.Name = "Q2" barSeries2.LegendTitle = "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "Le barSeries2.DataPoints.Add(New CategoricalDataPoint(153, "Harley")) barSeries2.DataPoints.Add(New CategoricalDataPoint(141, "White")) barSeries2.DataPoints.Add(New CategoricalDataPoint(130, "Smith")) barSeries2.DataPoints.Add(New CategoricalDataPoint(88, "Jones")) barSeries2.DataPoints.Add(New CategoricalDataPoint(109, "Marshall")) Me.RadChartView1.Series.Add(barSeries2) Me.RadChartView1.ShowTitle = True Me.RadChartView1.ShowLegend = True Me.RadChartView1.LegendTitle = "Legend" Me.RadChartView1.Size = New Size(500, 150) Me.RadChartView1.ShowPanZoom = True 'Me.SetupLineSeries() End Sub Private Sub RadButton1_Click(sender As Object, e As EventArgs) Handles RadButton1.Click Dim filePath As String = "..\..\exprotedChart2.png" Me.RadChartView1.ExportToImage(filePath, New Size(1000, 800), System.Drawing.Imaging.ImageFormat.Png) End Sub End Class Workaround: increase the size of the chart Public Class Form1 Sub New() InitializeComponent() Dim barSeries As New Telerik.WinControls.UI.BarSeries("Performance", "RepresentativeName") barSeries.Name = "Q1" barSeries.LegendTitle = "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" barSeries.DataPoints.Add(New CategoricalDataPoint(177, "Harley")) barSeries.DataPoints.Add(New CategoricalDataPoint(128, "White")) barSeries.DataPoints.Add(New CategoricalDataPoint(143, "Smith")) barSeries.DataPoints.Add(New CategoricalDataPoint(111, "Jones")) barSeries.DataPoints.Add(New CategoricalDataPoint(118, "Marshall")) Me.RadChartView1.Series.Add(barSeries) Dim barSeries2 As New Telerik.WinControls.UI.BarSeries("Performance", "RepresentativeName") barSeries2.Name = "Q2" barSeries2.LegendTitle = "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" + vbCrLf + "LegendTitle1" barSeries2.DataPoints.Add(New CategoricalDataPoint(153, "Harley")) barSeries2.DataPoints.Add(New CategoricalDataPoint(141, "White")) barSeries2.DataPoints.Add(New CategoricalDataPoint(130, "Smith")) barSeries2.DataPoints.Add(New CategoricalDataPoint(88, "Jones")) barSeries2.DataPoints.Add(New CategoricalDataPoint(109, "Marshall")) Me.RadChartView1.Series.Add(barSeries2) Me.RadChartView1.ShowTitle = True Me.RadChartView1.ShowLegend = True Me.RadChartView1.LegendTitle = "Legend" Me.RadChartView1.Size = New Size(500, 150) Me.RadChartView1.ShowPanZoom = True 'Me.SetupLineSeries() End Sub Dim size As Size Private Sub RadButton1_Click(sender As Object, e As EventArgs) Handles RadButton1.Click AddHandler Me.RadChartView1.SizeChanged, AddressOf RadChartView1_SizeChanged size = Me.RadChartView1.Size Me.RadChartView1.Size = New Size(1000, 800) End Sub Private Sub RadChartView1_SizeChanged(sender As Object, e As EventArgs) RemoveHandler Me.RadChartView1.SizeChanged, AddressOf RadChartView1_SizeChanged Dim filePath As String = "..\..\exprotedChart2.png" Me.RadChartView1.ExportToImage(filePath, Me.RadChartView1.Size, System.Drawing.Imaging.ImageFormat.Png) Me.RadChartView1.Size = size End Sub End Class
How to reproduce: Public Class Form1 Sub New() InitializeComponent() Me.SetupLineSeries() End Sub Private Sub SetupLineSeries() Dim splitContainer = New RadSplitContainer() splitContainer.SplitPanels.Add(New SplitPanel()) splitContainer.SplitPanels.Add(New SplitPanel()) splitContainer.SplitPanels(0).Controls.Add(Me.RadChartView1) Me.RadChartView1.Dock = DockStyle.Fill splitContainer.Orientation = Orientation.Horizontal splitContainer.Parent = Me splitContainer.Dock = DockStyle.Fill Dim lineSeries As New Telerik.WinControls.UI.LineSeries("2014") lineSeries.LegendTitle = "2014" lineSeries.ShowLabels = True lineSeries.DataPoints.Add(New CategoricalDataPoint(8000, "Jan")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8700, "Feb")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8500, "Mar")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8900, "Apr")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8400, "May")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8300, "Jun")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8600, "Jul")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8800, "Aug")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8400, "Sep")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8300, "Oct")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8500, "Nov")) lineSeries.DataPoints.Add(New CategoricalDataPoint(8100, "Dec")) Me.RadChartView1.Series.Add(lineSeries) Dim lineSeries2 As New Telerik.WinControls.UI.LineSeries("2015") lineSeries2.LegendTitle = "2015" lineSeries2.ShowLabels = True lineSeries2.DataPoints.Add(New CategoricalDataPoint(5800, "Jan")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(5900, "Feb")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(5700, "Mar")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(5500, "Apr")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(5300, "May")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(5600, "Jun")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(5800, "Jul")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(5800, "Aug")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(5900, "Sep")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(6100, "Oct")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(7900, "Nov")) lineSeries2.DataPoints.Add(New CategoricalDataPoint(7600, "Dec")) Me.RadChartView1.Series.Add(lineSeries2) Me.RadChartView1.ShowSmartLabels = True Me.RadChartView1.ShowTitle = True Me.RadChartView1.ShowLegend = True Me.RadChartView1.LegendTitle = "Legend" Dim verticalAxis As LinearAxis = RadChartView1.Axes.[Get](Of LinearAxis)(1) verticalAxis.Minimum = 4000 verticalAxis.Maximum = 20000 verticalAxis.MajorStep = 4000 Me.RadChartView1.ShowPanZoom = True End Sub End Class