I'd like the bars to look as per the attachment, with a shadow to the bottom and to the right.
With series defined as a BarSeries, I tried this, but it had no effect on the appearance of the bars:
series.BorderBoxStyle = Telerik.WinControls.BorderBoxStyle.FourBorders
series.BorderBottomShadowColor = Color.Gray
series.BorderRightShadowColor = Color.Gray
series.BorderRightWidth = 20
series.BorderBottomWidth = 40
Please could you let me know how to achieve this?
Leigh
4 Answers, 1 is accepted
Thank you for writing.
This is not supported out of the box, but can be achieved by using custom renderer. The attached example shows sample implementation for this.
Please let me know if there is something else I can help you with.
Dimitar
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
Hello Telerik Support,
I know this is an old post, but I found a design flaw (see: https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2214?view=vs-2019&redirectedfrom=MSDN). The current version (2020.2.512) is also affected.
The constructor of the class CartesianRenderer calls virtual method Initialize(). So you can't set any properties of the derived renderer class to use it in the overridden Initialize method. Here's some example code:
public
class
RenderParameter
{
//just an example
public
Color Color {
get
;
set
}
public
RenderParameter() {}
}
public
class
CustomCartesianRenderer : CartesianRenderer
{
private
RenderParameter RenderParameter {
get
;
set
; }
public
CustomCartesianRenderer(RenderParameter renderParameter, CartesianArea area) :
base
(area)
{
RenderParameter = renderParameter ??
throw
new
ArgumentNullException(nameof(renderParameter));
}
protected
override
void
Initialize()
{
base
.Initialize();
for
(
int
i = 0; i <
this
.DrawParts.Count; i++)
{
if
(
this
.DrawParts[i]
is
BarSeriesDrawPart barPart)
{
this
.DrawParts[i] =
new
CustomBarSeriesDrawPart(RenderParameter, (BarSeries)barPart.Element,
this
);
}
}
}
}
public
class
CustomBarSeriesDrawPart : BarSeriesDrawPart
{
private
RenderParameter RenderParameter {
get
; }
public
CustomBarSeriesDrawPart(RenderParameter renderParameter, BarSeries series, IChartRenderer renderer) :
base
(series, renderer)
{
RenderParameter = renderParameter ??
throw
new
ArgumentNullException(nameof(renderParameter));
}
public
override
void
DrawSeriesParts()
{
//here I want to use RenderParameter
}
}
Regards,
Stephan
In the DrawSeriesParts method of the custom BarSeriesDrawPart class you have access to the CartesianRenderer via the Renderer property. You need to cast it to the custom renderer that you have and thus you will have access to the RenderParameter property. Please refer to the following code snippet:
public Form1()
{
InitializeComponent();
this.radChartView1.CreateRenderer += new ChartViewCreateRendererEventHandler(radChartView1_CreateRenderer);
BarSeries barSeries = new BarSeries("Performance", "RepresentativeName");
barSeries.Name = "Q1";
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);
}
void radChartView1_CreateRenderer(object sender, ChartViewCreateRendererEventArgs e)
{
RenderParameter param = new RenderParameter();
param.Color = Color.Red;
e.Renderer = new CustomCartesianRenderer(param, e.Area as CartesianArea);
}
}
public class RenderParameter
{
//just an example
public Color Color { get; set; }
public RenderParameter()
{
}
}
public class CustomCartesianRenderer : CartesianRenderer
{
internal RenderParameter RenderParameter { get; set; }
public CustomCartesianRenderer(CartesianArea area) : base(area)
{
}
public CustomCartesianRenderer(RenderParameter renderParameter, CartesianArea area) : base(area)
{
RenderParameter = renderParameter ?? throw new ArgumentNullException(nameof(renderParameter));
}
protected override void Initialize()
{
base.Initialize();
for (int i = 0; i < this.DrawParts.Count; i++)
{
BarSeriesDrawPart linePart = this.DrawParts[i] as BarSeriesDrawPart;
if (linePart != null)
{
this.DrawParts[i] = new CustomBarSeriesDrawPart((BarSeries)linePart.Element, this);
}
}
}
}
public class CustomBarSeriesDrawPart : BarSeriesDrawPart
{
public CustomBarSeriesDrawPart(BarSeries series, IChartRenderer renderer) : base(series, renderer)
{
}
public override void DrawSeriesParts()
{
CustomCartesianRenderer customRenderer = this.Renderer as CustomCartesianRenderer;
RenderParameter param= customRenderer.RenderParameter;
Graphics graphics = customRenderer.Graphics;
RadGdiGraphics radGraphics = new RadGdiGraphics(graphics);
for (int j = 0; j < this.Element.DataPoints.Count; j++)
{
RadRect slot = this.Element.DataPoints[j].LayoutSlot;
RectangleF temp = new RectangleF((float)(this.OffsetX + slot.X), (float)(this.OffsetY + slot.Y), (float)slot.Width, (float)slot.Height);
RectangleF barBounds = new RectangleF(temp.X + 10,temp.Y + 10,temp.Width,temp.Height + 10);
DataPointElement childElement = (DataPointElement)this.Element.Children[j];
float realWidth = barBounds.Width * childElement.HeightAspectRatio;
barBounds.Width = realWidth;
barBounds.Height = Math.Max(barBounds.Height, 1f);
radGraphics.FillRectangle(barBounds, Color.LightGray);
}
base.DrawSeriesParts();
}
}
Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
Hello Dess,
your provided solution works fine. Thank you for your help.
Regards,
Stephan