I'm trying to create a report that groups data by a certain field and will then show a grap for each group. In my report I'm trying to use a datasource that contains the following data:
ID,X,Y,Group (<== column names)
0,0,1,1
1,1,1,1
2,0,2,2
3,2,2,2
4,0,3,3
5,3,3,3
This is what I have done so far:
- I've added a group to this report with the Grouping property set to '= Fields.Group'
- In the group header section I've added a textbox that prints the value for the 'current' Group
- In the detail section I've added textboxes that print the values for X and Y
This works as I would expect it to, but now I want to add a graph (Type = Point) to the group header section that will show the two points for each group with the above coordinates. So what I want to achieve is that three headers are generated and that each one has a graph that shows two points.
I'm trying to use the needdatasource event that gets thrown three times in this case. In my attempt to get the above working, I used the following code:
| Private Sub Chart1_NeedDataSource(ByVal sender As Object, ByVal e As System.EventArgs) Handles Chart1.NeedDataSource |
| Dim myChart As Telerik.Reporting.Processing.Chart = DirectCast(sender, Telerik.Reporting.Processing.Chart) |
| If Chart1.Series.Count = 0 Then |
| Chart1.Series.Add(New Charting.ChartSeries("Test", Charting.ChartSeriesType.Point)) |
| Chart1.Series(0).DataXColumn = "Fields.X" |
| Chart1.Series(0).DataYColumn = "Fields.Y" |
| End If |
| If myChart.DataSource Is Nothing Then myChart.DataSource = Me.DataSource |
| End Sub |
What am I doing wrong and how do I get this to work for each group header section so that I have three different graphs with the following points:
Graph 1: 0,1 and 1,1
Graph 2: 0,2 and 2,2
Graph 3: 0,3 and 3,3
15 Answers, 1 is accepted
Currently this scenario can be achieved only with code. Here is a sample code snippet:
Private Sub Chart1_NeedDataSource(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Chart1.NeedDataSource Dim dataTable = New DataTable() dataTable.Columns.Add("ID", GetType(Integer)) dataTable.Columns.Add("X", GetType(Integer)) dataTable.Columns.Add("Y", GetType(Integer)) dataTable.Columns.Add("Group", GetType(Integer)) dataTable.Rows.Add(New Object() {0, 0, 1, 1}) dataTable.Rows.Add(New Object() {1, 1, 1, 1}) dataTable.Rows.Add(New Object() {2, 0, 2, 2}) dataTable.Rows.Add(New Object() {3, 2, 2, 2}) dataTable.Rows.Add(New Object() {4, 0, 3, 3}) dataTable.Rows.Add(New Object() {5, 3, 3, 3}) Dim chart = CType(sender, Telerik.Reporting.Processing.Chart) Dim chartDef = CType(chart.ItemDefinition, Telerik.Reporting.Chart) chartDef.Series.Clear() Dim xIndexesList = New List(Of Double) For Each row In dataTable.DefaultView Dim chartSeries As Telerik.Reporting.Charting.ChartSeries Dim seriesName = row("Group").ToString() chartSeries = chartDef.Series.GetByName(seriesName) If chartSeries Is Nothing Then chartSeries = New Telerik.Reporting.Charting.ChartSeries(seriesName) chartDef.Series.Add(chartSeries) End If Dim seriesItem = New Telerik.Reporting.Charting.ChartSeriesItem Dim xValue = CType(row("X"), Double) If Not xIndexesList.Contains(xValue) Then xIndexesList.Add(xValue) End If seriesItem.XValue = xIndexesList.IndexOf(xValue) seriesItem.YValue = CType(row("Y"), Double) chartSeries.Items.Add(seriesItem) Next chartDef.PlotArea.XAxis.Items.Clear() chartDef.PlotArea.XAxis.AutoShrink = False chartDef.PlotArea.XAxis.AutoScale = False chartDef.PlotArea.XAxis.AddRange(0, xIndexesList.Count - 1, 1) End SubHope it helps.
All the best,
Chavdar
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Is there a 'best-practice' way in which I can achieve this?
What I've done so far, is to dynamically add items to the graph each time when the 'needdatasource' event is raised. I then only add the items that belong to the current group by selecting them from my datasource. It's not the most spectacular looking code, because at run-time I don't have a clue what the current grouping value is that Telerik uses. Therefore I store each grouping value in a list and each time when the needdatasource event is raised, I collect the (n+1)th item of that list. I hope you can provide me a nicer looking solution for this.
How did you get the value of the current group? I have been struggling with the same issue.
Thanks,
Joe
1. I supply a datasource which needs to be grouped by only one value
2. The values in this datasource are sorted by this grouping value
3. I assume that Telerik will then throw the needdatasource event for each 'grouping value' in the way that I have sorted them
So at run-time I keep track of how many times the needdatasource event is raised. When it is raised the first time, I assume that this is the first grouping value in my datasource. I then make a selection on my datasource and add the values that belong to this 'grouping value'. When the event is raised the second time, I get the second 'grouping value', etc, etc...
So far this has produced the result that I was looking for, but as you can see, I have made a few assumptions along the way and I can't be 100% sure that Telerik will really always group my datasource in the way I want it to.
May be someone from Telerik can shed some light on this issue?
Currently the chart's data source is different from the report's data source so you cannot reuse its grouping, sorting or filtering automatically. This also means that the data for the chart should be prepared manually to reflect the desired result.
Here is an example which can be extended to fit the actual scenario with a few modifications. The key steps are as follows:
1. Get the current grouping value from the group header section's DataObject.(handle [GroupHeaderSection].ItemDataBinding event).
2. Create a filtering expression based on this value
3. Apply filtering
4. Get the result and fill the chart with data.
Partial Public Class Report1 Inherits Telerik.Reporting.Report Public Sub New() InitializeComponent() 'One time chart configuration settings Me.Chart1.PlotArea.XAxis.AutoScale = False Me.Chart1.PlotArea.XAxis.AutoShrink = False Me.Chart1.PlotArea.XAxis.AddRange(0, 5, 1) 'Dummy data source Dim dataTable = New DataTable() dataTable.Columns.Add("ID", GetType(Integer)) dataTable.Columns.Add("X", GetType(Integer)) dataTable.Columns.Add("Y", GetType(Integer)) dataTable.Columns.Add("Group", GetType(Integer)) dataTable.Rows.Add(New Object() {0, 0, 1, 1}) dataTable.Rows.Add(New Object() {1, 1, 1, 1}) dataTable.Rows.Add(New Object() {2, 0, 2, 2}) dataTable.Rows.Add(New Object() {3, 2, 2, 2}) dataTable.Rows.Add(New Object() {4, 0, 3, 3}) dataTable.Rows.Add(New Object() {5, 3, 3, 3}) Me.DataSource = dataTable End Sub Private Sub GroupHeaderSection1_ItemDataBinding(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupHeaderSection1.ItemDataBinding Dim groupHeaderSection As Telerik.Reporting.Processing.GroupSection = CType(sender, Telerik.Reporting.Processing.GroupSection) Dim report As Telerik.Reporting.Processing.Report = groupHeaderSection.Report Dim group = groupHeaderSection.DataObject.Item("Group") Dim table As DataTable = CType(report.DataSource, DataTable) Dim rows() As DataRow = table.Select(String.Format(CultureInfo.InvariantCulture, "Group={0}", group)) Dim chart As Telerik.Reporting.Processing.Chart = groupHeaderSection.ChildElements.Find("Chart1", True)(0) Dim chartDef As Telerik.Reporting.Chart = chart.ItemDefinition chartDef.Series.Clear() Dim chartSeries As New Telerik.Reporting.Charting.ChartSeries() Dim row As DataRow For Each row In rows Dim seriesItem As Telerik.Reporting.Charting.ChartSeriesItem = New Telerik.Reporting.Charting.ChartSeriesItem() seriesItem.XValue = CType(row("X"), Double) seriesItem.YValue = CType(row("Y"), Double) chartSeries.Items.Add(seriesItem) Next chartDef.Series.Add(chartSeries) End SubEnd ClassHope this helps.
Greetings,
Chavdar
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
You are my hero. This is exactly what I was looking for.
Regards,
Jaap
Jaap,
Did you ever get this to work? I'm afraid I was forced to go with an alternate solution based on time constraints.
Thanks,
Joe
| Dim group = groupHeaderSection.DataObject.Item("Group") |
| Dim table As DataTable = CType(report.DataSource, DataTable) |
| Dim rows() As DataRow = table.Select(String.Format(CultureInfo.InvariantCulture, "Group={0}", group)) |
| Dim chart As Telerik.Reporting.Processing.Chart = groupHeaderSection.ChildElements.Find("Chart1", True)(0) |
| Dim chartDef As Telerik.Reporting.Chart = chart.ItemDefinition |
| chartDef.Series.Clear() |
| Dim chartSeries As New Telerik.Reporting.Charting.ChartSeries() |
| Dim row As DataRow |
| For Each row In rows |
| Dim seriesItem As Telerik.Reporting.Charting.ChartSeriesItem = New Telerik.Reporting.Charting.ChartSeriesItem() |
| seriesItem.XValue = CType(row("X"), Double) |
| seriesItem.YValue = CType(row("Y"), Double) |
| chartSeries.Items.Add(seriesItem) |
| Next |
| chartDef.Series.Add(chartSeries) |
I'm posting the C# code for the example my colleague provided:
public partial class Report2 : Telerik.Reporting.Report { public Report2() { // // Required for telerik Reporting designer support // InitializeComponent(); this.chart1.PlotArea.XAxis.AutoScale = false; this.chart1.PlotArea.XAxis.AutoShrink = false; this.chart1.PlotArea.XAxis.AddRange(0, 5, 1); //Dummy data source DataTable dataTable = new DataTable(); dataTable.Columns.Add("ID", typeof(int)); dataTable.Columns.Add("X", typeof(int)); dataTable.Columns.Add("Y", typeof(int)); dataTable.Columns.Add("Group", typeof(int)); dataTable.Rows.Add(new object[] {0, 0, 1, 1}); dataTable.Rows.Add(new object[] {1, 1, 1, 1}); dataTable.Rows.Add(new object[] {2, 0, 2, 2}); dataTable.Rows.Add(new object[] {3, 2, 2, 2}); dataTable.Rows.Add(new object[] {4, 0, 3, 3}); dataTable.Rows.Add(new object[] {5, 3, 3, 3}); this.DataSource = dataTable; // // TODO: Add any constructor code after InitializeComponent call // } private void groupHeaderSection1_ItemDataBinding(object sender, EventArgs e) { Telerik.Reporting.Processing.GroupSection groupHeaderSection = (Telerik.Reporting.Processing.GroupSection)sender; Telerik.Reporting.Processing.Report report = groupHeaderSection.Report; var group = groupHeaderSection.DataObject["Group"]; DataTable table = (DataTable)report.DataSource; DataRow[] rows = table.Select(string.Format(CultureInfo.InvariantCulture, "Group={0}", group)); Telerik.Reporting.Processing.Chart chart = (Telerik.Reporting.Processing.Chart)groupHeaderSection.ChildElements.Find("Chart1", true)[0]; Telerik.Reporting.Chart chartDef = (Telerik.Reporting.Chart)chart.ItemDefinition; chartDef.Series.Clear(); Telerik.Reporting.Charting.ChartSeries chartSeries = new Telerik.Reporting.Charting.ChartSeries(); foreach (var row in rows) { Telerik.Reporting.Charting.ChartSeriesItem seriesItem = new Telerik.Reporting.Charting.ChartSeriesItem(); seriesItem.XValue = Convert.ToDouble(row["X"]); seriesItem.YValue = Convert.ToDouble(row["Y"]); chartSeries.Items.Add(seriesItem); } chartDef.Series.Add(chartSeries); } }where do note that Group is a column from the sample datasource we bind the report to in the report constructor and not the name of a report group.
All the best,
Steve
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>
My report has a table and a chart. The table gets it data from a Telerik.Reporting.ObjectDataSource set in the designer window. The chart gets it data from the code behind method below inside chart_NeedDataSource.
System.Collections.ObjectModel.Collection<ReportCommonMatrixDataContract> reportCollection = ReportCommonMatrixCollection.GetSmokingStatusReport((DateTime)Report.ReportParameters[0].Value, (DateTime)Report.ReportParameters[1].Value, (string)Report.ReportParameters[2].Value, (int?)Report.ReportParameters[3].Value, (int?)Report.ReportParameters[4].Value);Since the table and chart shows the same data I want to use the reports Telerik.Reporting.ObjectDataSource to provide the data like this:
System.Collections.ObjectModel.Collection<ReportCommonMatrixDataContract> reportCollection = (System.Collections.ObjectModel.Collection<ReportCommonMatrixDataContract>)objectDataSource1.DataSource;This causes an error "An error has occurred while processing Chart 'chart1':
Unable to cast object of type 'System.RuntimeType' to type 'System.Collections.ObjectModel.Collection`1[Hemit.Mqr.Common.DataContract.ReportCommonMatrixDataContract]'."
Why doesn't his work?
Regards, Roy
The declarative data source components are intended to specify declaratively how to retrieve the data for the report. They do not contain any data at all, they only specify the means how to obtain it (e.g. in the case of SqlDataSource - by executing a SQL query against a database, or in the case of ObjectDataSource - by invoking a method/property of a custom business object, etc.). So you see the cast you have is really incorrect.
In order to achieve your requirement our suggestion is to use a new approach the involves bindings. For more information refer to this forum thread.
Kind regards,
Steve
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
From your screenshot it is not clear what is the data structure and report definition. In my colleagues example, the group is not static, thus it has DataObject containing the current group's data.
Notice the Chart item is now obsolete. Please consider switching to the new Graph item, which provides greater design time support for expressions, styling and interactivity.
If you need further help, please open a support thread and send us the report definition with some sample data.
Regards,
Stef
Telerik
Have you tried the new visualization options in Telerik Reporting Q2 2013? You can get them from your account.
Hi ,
We are facing one Issue and could not able to resolve. We are working with Telerik Graph Control and using Chart type "Line with Marker". Issue is once will prepare the graph on PDF, ​Data Point Marker and ​Data point Label are overlapping with each other (See attached Screenshot). Please let me know if any property available in Telerik to resolve this Issue. I am using 2013 Q3 License ​version of Telerik.
Thanks for the help in advance.
Please test if setting the YAxis - Scale - Maximum to 110 (based on the data from the screenshot) causes the data point labels to be displayed as expected. Note that you wil have to provide value for the YAxis - Scale - Minimum as well.
If yes, the issue is that the labels are pushed down to be gathered in the visible plot area. To avoid the issue you can check the maximum displayed value by analyzing the data in code, and then set the number as axis - Scale - Maximum in the report constructor.
In the latest Telerik Reporting Q2 2015 version there is an option to use a binding to set the minimum and maximum of the scale - How to: Use Bindings to Control the Coordinate System Properties.
Regards,
Stef
Telerik