How do I set the color of the bars in a bar chart?
In the designer I have the Series Appearance,Appearance,FillStyle,FillSettings,MainColor = CornflowerBlue
and I have the PlotArea,DataTable,Appearance,FillStyle,FillSettings,MainColor = CornflowerBlue
but this cannot be right as my bars are still some aqua blue color.
???
Dan
15 Answers, 1 is accepted
Besides setting the ChartSeries.Appearance.FillStyle.MainColor, you would need to set the FillType as well. Here is the designer-generated code that produces the desired effect:
chartSeries1.Appearance.FillStyle.FillType = Telerik.Reporting.Charting.Styles.FillType.Solid; |
chartSeries1.Appearance.FillStyle.MainColor = System.Drawing.Color.Red; |
We have attached a sample class library as well.
Sincerely yours,
Manuel
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
Manuel,
The attached class library appears to be empty. Can you repost?
It seems that the chart series items are available only in the ItemDataBound event, so I tried the following code, but it does not affect the color of the chart bars.
private
void chart1_ItemDataBound(object sender, EventArgs e)
{
foreach (ChartSeriesItem item in chart1.Series[0].Items)
{
item.Appearance.FillStyle.MainColor =
Color.CornflowerBlue;
item.Appearance.FillStyle.FillType = Telerik.Reporting.Charting.Styles.
FillType.Solid;
item.Label.Appearance.FillStyle.MainColor =
Color.Black;
item.Label.Appearance.FillStyle.FillType = Telerik.Reporting.Charting.Styles.
FillType.Solid;
}
}
Dan
Actually as explained in this help article, if you want to make any changes to the definition chart item, NeedDataSource event is the event for you. Moving your code to the NeedDataSource event should work as expected.
Please try it and let us know if further help is needed.
Sincerely yours,
Steve
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
In chart1_NeedDataSource, chart1.Series.Count = 0
I cannot set properties on a series that does not yet exist.
Dan
Find attached a modified version of the class library from previous post. Note that the bar chart color is set both declaratively (from report designer) and programmatically in NeedDataSource event.
Sincerely yours,
Steve
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
However, in my case, the series is generated dynamically via SQL data query into a DataSource which is applied to the chart in the NeedDataSource event routine. In which case the items are not yet available for property setting at that point. The series items are only available in the ItemDataBound routine. And setting the FillStyle properties in the ItemDataBound routine does not affect the bar colors.
Dan
You're correct. I'm afraid however that the only solution would be to create the chart series at runtime while setting their color as well, before populating the chart from your db.
Kind regards,
Steve
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
If generating the series at runtime is possible, I'm not sure how it is. My case is:
Two report parameters.
User selects the two parameters.
In NeedDataSource, the report parameters affect the SQL record query, and so, the number of series items is dependent on the report parameters chosen.
When is the series created in this case?
In NeedDataSource, can I add series1, and add the appropriate number of series items, set their color, then assign the DataSource to the chart?
Thanks.
Dan
ps: Is there a reason why I cannot assign the color properties in the ItemDataBound routine?
You can create and customize the chart entirely in the NeedDataSouce event of the Chart report item. Consider the following example:
private void chart1_NeedDataSource(object sender, EventArgs e) |
{ |
DataTable table = new DataTable(); |
table.Columns.Add("Value", typeof(double)); |
table.Columns.Add("Color", typeof(Color)); |
table.Rows.Add(new object[] { 1.0, Color.Red }); |
table.Rows.Add(new object[] { 1.5, Color.Green }); |
table.Rows.Add(new object[] { 2.0, Color.Blue }); |
table.Rows.Add(new object[] { 3.2, Color.Yellow }); |
Telerik.Reporting.Processing.Chart chart = (Telerik.Reporting.Processing.Chart)sender; |
Telerik.Reporting.Chart chartDef = (Telerik.Reporting.Chart)chart.ItemDefinition; |
Telerik.Reporting.Charting.ChartSeries series = new Telerik.Reporting.Charting.ChartSeries(); |
foreach (DataRowView rowView in table.DefaultView) |
{ |
Telerik.Reporting.Charting.ChartSeriesItem seriesItem = new Telerik.Reporting.Charting.ChartSeriesItem(); |
seriesItem.YValue = (double)rowView["Value"]; |
seriesItem.Appearance.FillStyle.FillType = Telerik.Reporting.Charting.Styles.FillType.Solid; |
seriesItem.Appearance.FillStyle.MainColor = (Color)rowView["Color"]; |
series.AddItem(seriesItem); |
} |
chartDef.Series.Clear(); |
chartDef.Series.Add(series); |
} |
Note that when creating the series and the series items programmatically you do not have to set the DataSource property.
Sincerely yours,
Chavdar
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
The problem here is with using the standard databinding, using NeedDataSource, into the chart which is the convenient way to populate the chart data from the database data. Here is your ProcessItem code:
protected override void ProcessItem()
{
this.chart.RaiseNeedDataSource(this, EventArgs.Empty);
Chart chart = ((IChartComponent) this.chart).Chart;
if (chart.DataManager.DataSource != this.dataSource)
{
chart.DataManager.DataSource = this.dataSource;
chart.DataManager.DataBind();
}
chart.ImageFormat = ImageFormat.Emf;
this.chartImage = chart.GetImage(this.chart.Width.Pixels, this.chart.Height.Pixels);
}
The DataSource is bound and then the chart image is immediately created. There is no way to adjust the Appearance properties of the series. It would be convenient to add an event or change the flow of the current events (i.e. put ItemDataBound BEFORE the chart.GetImage call) so that a user of your architecture could adjust necessary properties before the chart image is rendered.
Your suggestion above is to manually populate the chart series in the NeedDataSource routine. Alternatively, I have used this method. Add an ItemDataBound routine which does the formatting using the Appearance properties of the chart items and then calls the ProcessItem() method of the chart using reflection to generate the chart image again.
private void chart1_ItemDataBound(object sender, EventArgs e)
{
Telerik.Reporting.Processing.Chart chart = (sender as Telerik.Reporting.Processing.Chart);
if (chart != null)
{
Telerik.Reporting.Chart ch = chart.ItemDefinition as Telerik.Reporting.Chart;
// adjust chart properties
foreach (Telerik.Reporting.Charting.ChartSeries series in (ch as Telerik.Reporting.Charting.IChartComponent).Chart.Series)
{
series.Appearance.FillStyle.FillType = Telerik.Reporting.Charting.Styles.FillType.Gradient;
series.Appearance.FillStyle.MainColor = Color.FromArgb(18, 97, 146);
series.Appearance.FillStyle.SecondColor = Color.FromArgb(199, 233, 254);
foreach (Telerik.Reporting.Charting.ChartSeriesItem item in series.Items)
{
item.Label.TextBlock.Appearance.TextProperties.Color = Color.Black;
}
}
// fire ProcessItem() again to regenerate chart image now that we have changed our appearances
MethodInfo meth = chart.GetType().GetMethod("ProcessItem", BindingFlags.NonPublic | BindingFlags.Instance);
meth.Invoke(chart, null);
}
}
Then make sure to not query the database for the chart data a second time in NeedDataSource:
private int boundCount = 0;
private void chart1_NeedDataSource(object sender, EventArgs e)
{
boundCount++;
if (boundCount % 2 == 1)
{
try
{
string commandText = "select database query";
SqlDataAdapter adapter = new SqlDataAdapter(commandText, localConnectionstring);
DataSet ds = new DataSet();
adapter.Fill(ds);
(sender as Telerik.Reporting.Processing.Chart).DataSource = ds.Tables[0].DefaultView;
}
catch (Exception ex)
{
log1.WriteError(ex);
}
}
}
We're very much aware of the limitations imposed by the current chart item. As you have probably noticed, it is the only report item that does not use the reporting data engine and this is one of the reasons why it cannot be databoud from the report designer. Improving the reporting chart item is in our TODO list and we hope that we would soon have the time to work in that direction.
For the time being, creating the series and the series items programmatically (excluding your approach which is a bit of a hack using reflection) is the only workaround.
Kind regards,
Steve
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
-Deva
private void yourOwnChartName_ItemDataBound(object sender, EventArgs e)
{
Telerik.Reporting.Processing.Chart chart = (sender as Telerik.Reporting.Processing.Chart);
if (chart != null)
{
//adjust size of chart.
//Basically start with a minimum size to display the axes. In this case it's 30, which corresponds roughly to a third of an inch
//Add to the size of the chart based on how many items are in your dataset.
//In this example, I add roughly a third of an inch for every item.
chart.Height = new Unit(30 + yourOwnChartName.Series[0].Items.Count * 30);
// fire ProcessItem() again to regenerate chart image now that we have changed our appearances
System.Reflection.MethodInfo meth = chart.GetType().GetMethod("ProcessItem", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
meth.Invoke(chart, null);
}
}
My chart was assigned a dataset via the designer, so I didn't need to implement the NeedDataSource method.