Hi everybody,
Indeed, there is a problem to distinguish a bar which a Renderer is called for. A BarSeries's Renderer is called for shadows as well, not for bars only. Also a record parameter might be undefined.
I found some threads which looks to be related to the problem, but there is no solution for your case.
http://www.sencha.com/forum/showthread.php?126251
http://www.sencha.com/forum/showthread.php?132968
After a lot of investigation of the the logic of rendering a BarSeries with multiple YFields, I was able to come up with the example below. I don't think it will work in all possible cases, but it appears to be working well for that specific case.
Example
<%@ Page Language="C#" %>
<%@ Register assembly="Ext.Net" namespace="Ext.Net" tagprefix="ext" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
Store s = this.Chart1.GetStore();
s.DataSource = new object[]
{
new
{
Name = "Category 1",
Data1 = -10,
Data2 = 100
},
new
{
Name = "Category 2",
Data1 = 20,
Data2 = -90
},
new
{
Name = "Category 3",
Data1 = -30,
Data2 = 80
}
};
}
}
</script>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET v2 Example</title>
<script>
Ext.chart.series.Bar.override({
renderShadows: function(i, barAttr, baseAttrs, bounds) {
var me = this,
chart = me.chart,
surface = chart.surface,
animate = chart.animate,
stacked = me.stacked,
shadowGroups = me.shadowGroups,
shadowAttributes = me.shadowAttributes,
shadowGroupsLn = shadowGroups.length,
store = chart.getChartStore(),
column = me.column,
items = me.items,
shadows = [],
zero = bounds.zero,
shadowIndex, shadowBarAttr, shadow, totalDim, totalNegDim, j, rendererAttributes;
if ((stacked && (i % bounds.groupBarsLen === 0)) || !stacked) {
j = i / bounds.groupBarsLen;
//create shadows
for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
shadowBarAttr = Ext.apply({}, shadowAttributes[shadowIndex]);
shadow = shadowGroups[shadowIndex].getAt(stacked ? j : i);
Ext.copyTo(shadowBarAttr, barAttr, 'x,y,width,height');
if (!shadow) {
shadow = surface.add(Ext.apply({
type: 'rect',
group: shadowGroups[shadowIndex]
}, Ext.apply({}, baseAttrs, shadowBarAttr)));
}
if (stacked) {
totalDim = items[i].totalDim;
totalNegDim = items[i].totalNegDim;
if (column) {
shadowBarAttr.y = zero + totalNegDim - totalDim - 1;
shadowBarAttr.height = totalDim;
}
else {
shadowBarAttr.x = zero - totalNegDim;
shadowBarAttr.width = totalDim;
}
}
rendererAttributes = me.renderer(shadow, store.getAt(j), shadowBarAttr, i, store, true); // passed true as the last argument to determine it is a shadow or not in a Renderer call
rendererAttributes.hidden = !!barAttr.hidden;
if (animate) {
me.onAnimate(shadow, { to: rendererAttributes });
}
else {
shadow.setAttributes(rendererAttributes, true);
}
shadows.push(shadow);
}
}
return shadows;
}
});
</script>
<script>
var barRenderer = function(sprite, record, attr, index, store, isShadow) {
var barIndex,
data,
series = this;
if (!isShadow) {
barIndex = index % series.yField.length;
record = store.getAt(Math.floor(index / series.yField.length));
switch (barIndex) {
case 0: data = record.get(series.yField[0]); break;
case 1: data = record.get(series.yField[1]); break;
}
if (data < 0) {
attr.fill = "rgb(255, 0, 0)";
} else {
attr.fill = "rgb(0, 255, 0)";
}
}
return attr;
};
</script>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />
<ext:Panel
runat="server"
Title="Bar Renderer"
Width="400"
Height="300"
Layout="FitLayout">
<Items>
<ext:Chart ID="Chart1" runat="server">
<Store>
<ext:Store runat="server" >
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="Name" />
<ext:ModelField Name="Data1" />
<ext:ModelField Name="Data2" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<Axes>
<ext:NumericAxis Fields="Data1,Data2" Position="Bottom" Minimum="-100" />
<ext:CategoryAxis Fields="Name" Position="Left" />
</Axes>
<Series>
<ext:BarSeries
Axis="Bottom"
XField="X"
YField="Data1,Data2">
<Renderer Fn="barRenderer" />
</ext:BarSeries>
</Series>
</ext:Chart>
</Items>
</ext:Panel>
</form>
</body>
</html>