I'm building a Column chart with System.Web.UI.DataVisualization.Charting and would like to show a dotted line to represent an average. StripeLine seems to be exactly what I'm looking for except it sits under/behind the columns (see example).
Is there a way to adjust the "Z-Index" of a StripeLine so that it is shown in front of/on top of the Series?
I don't see a property for this and changing the order I add the Series and StripeLine doesn't make a difference.
You can use Annotations
double avg = Chart1.Series[0].Points.Average(p => p.XValue);
double lineHeight = avg;
HorizontalLineAnnotation ann = new HorizontalLineAnnotation();
ann.AxisX = Chart1.ChartAreas[0].AxisX;
ann.AxisY = Chart1.ChartAreas[0].AxisY;
ann.IsSizeAlwaysRelative = false;
ann.AnchorY = lineHeight;
ann.IsInfinitive = true;
ann.ClipToChartArea = Chart1.ChartAreas[0].Name; ann.LineColor = Color.Red; ann.LineWidth = 3;
Chart1.Annotations.Add(ann);
HTML Code
<asp:Chart runat="server" ID="Chart1" ImageStorageMode="UseImageLocation" Width="800px" Height="400px" OnClick="Chart1_Click">
<ChartAreas >
<asp:ChartArea></asp:ChartArea>
</ChartAreas>
<series>
<asp:Series Name="Students" BorderColor="180, 26, 59, 105">
<Points>
<asp:DataPoint AxisLabel="jon" XValue="5" YValues="4" />
<asp:DataPoint AxisLabel="kon" XValue="15" YValues="44" />
<asp:DataPoint AxisLabel="pol" XValue="85" YValues="90" />
</Points>
</asp:Series>
</series>
</asp:Chart>
Code for Text Annotation
TextAnnotation txtAnn = new TextAnnotation();
txtAnn.AxisX = Chart1.ChartAreas[0].AxisX;
txtAnn.AxisY = Chart1.ChartAreas[0].AxisY;
txtAnn.IsSizeAlwaysRelative = false;
txtAnn.AnchorY = lineHeight;
txtAnn.AnchorX = Chart1.Series[0].Points.Last().XValue;
txtAnn.AnchorAlignment = ContentAlignment.BottomLeft;
txtAnn.Text = "DivisionOne(35.5)";
txtAnn.ClipToChartArea = Chart1.ChartAreas[0].Name; txtAnn.ForeColor = Color.Red;
Chart1.Annotations.Add(txtAnn);
You can get more information here
More Information About Annotations
Chart Image
You can just use the text property of the stripeline
Chart1.ChartAreas("ChartArea1").AxisY.StripLines(0).Text = "Line
Title"
Related
I am using MS Chart Control in ASP.Net using VB.Net. The chart type is Pie. I am facing a weird problem where the number of items displayed in the legend is square of the number of Series present. This means if I have 2 series added to the pie chart, 4 items are displayed in legend and if I have 7 series added to the pie chart, 49 items appear in the legend. The 1st set of 7 items displaying the correct data and the others just displaying 0.
Here is the markup of my chart control in ASPX -
<asp:Chart runat="server" ID="chartX" CssClass="chart" Width="420px" Height="500px" ImageType="Jpeg">
<Series></Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1"></asp:ChartArea>
</ChartAreas>
<Legends>
<asp:Legend Docking="Bottom" Alignment="Center" Font="Calibri"></asp:Legend>
</Legends>
</asp:Chart>
Here is the code to populate chart control in ASPX.vb -
Dim table As DataTable = PopulateData()
Dim dv As DataView = New DataView(table, "Count > 0", "", DataViewRowState.OriginalRows)
For Each r As DataRow In dv.ToTable().Rows
Dim series As String = r("Name").ToString()
chartX.Series.Add(series)
chartX.Series(series).ChartType = DataVisualization.Charting.SeriesChartType.Pie
chartX.Series(series).XValueMember = "Name"
chartX.Series(series).YValueMembers = "Count"
chartX.ChartAreas(0).Area3DStyle.Enable3D = True
chartX.Series(series).Label = "#VALX" & Environment.NewLine & "(#PERCENT)"
chartX.Series(series)("PieLabelStyle") = "Disabled"
Next
chartX.DataSource = dv
chartX.DataBind()
Hoping for any answers.
If I'm not mistaken, you are adding a new series for each row in you table. Instead you should be adding the series once for the table and then binding your data.
You do not need to iterate through all rows when setting up your graph. Do it only once binding to the table. I never touch VB, but it should looks something like this
Dim table As DataTable = PopulateData()
Dim dv As DataView = New DataView(table, "Count > 0", "", DataViewRowState.OriginalRows)
' setup just once
Dim series As String = "Series Name"
chartX.Series.Add(series)
chartX.Series(series).ChartType = DataVisualization.Charting.SeriesChartType.Pie
chartX.Series(series).XValueMember = "Name"
chartX.Series(series).YValueMembers = "Count"
chartX.ChartAreas(0).Area3DStyle.Enable3D = True
chartX.Series(series).Label = "#VALX" & Environment.NewLine & "(#PERCENT)"
chartX.Series(series)("PieLabelStyle") = "Disabled"
' bind to the entire set
chartX.DataSource = dv
chartX.DataBind()
I have following SQL Server Result.
How to create a stacked column chart with asp.net 4 chart control?
Hospital September October April
OMD 10 20 15
IRH 15 16 18
Something like this:
Here is an example:
ASPX:
<asp:Chart ID="chart1" runat="server">
<Series>
<asp:Series Name="Series1" Label="September"></asp:Series>
<asp:Series Name="Series2" Label="October"></asp:Series>
<asp:Series Name="Series3" Label="April"></asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1"></asp:ChartArea>
</ChartAreas>
</asp:Chart>
<asp:Button ID="Button1" runat="server" Text="Graph" onclick="Button1_Click" />
C# Code-Behind:
protected void Button1_Click(object sender, EventArgs e)
{
// September Data
Chart1.Series[0].Points.Add(new DataPoint(0, 10));
Chart1.Series[0].Points.Add(new DataPoint(1, 15));
// October Data
Chart1.Series[1].Points.Add(new DataPoint(0, 20));
Chart1.Series[1].Points.Add(new DataPoint(1, 16));
// April Data
Chart1.Series[2].Points.Add(new DataPoint(0, 15));
Chart1.Series[2].Points.Add(new DataPoint(1, 18));
foreach (Series cs in chart1.Series)
cs.ChartType = SeriesChartType.StackedColumn;
}
Or with SQL Data source ds you can do the following directly:
DataTable dt = new DataTable();
dt = ds.Tables[0];
DataView dv = new DataView(dt);
chart1.DataSource = dv;
chart1.DataBind();
foreach (Series cs in chart1.Series)
cs.ChartType = SeriesChartType.StackedColumn;
I want to add a spline graphic and a points graphic on the same asp.net chart. Can somebody show an explicite example of how you do that?
Thank you.
Would be nice to know if you want a C# or a Visual Basic example. I've got a Visual Basic one for you. (You could convert it to C# with an online converter). I hope this helps you.
.aspx file:
<form id="form1" runat="server">
<div>
<asp:Chart ID="Chart1" runat="server">
<ChartAreas>
<asp:ChartArea Name="ChartArea1"></asp:ChartArea>
</ChartAreas>
</asp:Chart>
</div>
</form>
.vb file:
Imports System.Web.UI.DataVisualization.Charting
Imports System.Drawing
Public Class ChartExample
Inherits System.Web.UI.Page
Private Sub Page_load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Add the title
Chart1.Titles.Add("Title1")
' Set the text of the title
Chart1.Titles("Title1").Text = "Chart Area 1 Title"
' Dock the title to a ChartArea
Chart1.Titles("Title1").DockedToChartArea = "ChartArea1"
' Creating the series
Dim series1 As New Series("Series1")
Dim series2 As New Series("Series2")
' Setting the Chart Type
series1.ChartType = SeriesChartType.Spline
series2.ChartType = SeriesChartType.Point
' Adding some points
series1.Points.AddXY(0, 10)
series1.Points.AddXY(5, 16)
series1.Points.AddXY(10, 9)
series1.Points.AddXY(15, 32)
series1.Points.AddXY(20, 21)
series2.Points.AddXY(0, 5)
series2.Points.AddXY(5, 12)
series2.Points.AddXY(10, 18)
series2.Points.AddXY(15, 11)
series2.Points.AddXY(20, 25)
' Add the series to the chart
Chart1.Series.Add(series1)
Chart1.Series.Add(series2)
' Set the chart's height and width
Chart1.Width = 600
Chart1.Height = 600
' Setting the X Axis
Chart1.ChartAreas("ChartArea1").AxisX.IsMarginVisible = True
Chart1.ChartAreas("ChartArea1").AxisX.Interval = 1
Chart1.ChartAreas("ChartArea1").AxisX.Maximum = [Double].NaN
Chart1.ChartAreas("ChartArea1").AxisX.Title = "x"
Chart1.ChartAreas("ChartArea1").AxisX.TitleFont = New Font("Sans Serif", 10, FontStyle.Bold)
' Setting the Y Axis
Chart1.ChartAreas("ChartArea1").AxisY.Interval = 2
Chart1.ChartAreas("ChartArea1").AxisY.Maximum = [Double].NaN
Chart1.ChartAreas("ChartArea1").AxisY.Title = "y"
Chart1.ChartAreas("ChartArea1").AxisY.TitleFont = New Font("Sans Serif", 10, FontStyle.Bold)
End Sub
End Class
I want to present some condensed data to the user using the Chart component.
SQL (C# / Oracle):
SELECT c.date, c.approved, count(distinct c.f1) amt_c, count(b.f1) amt_b, sum(b.value) sum_values
FROM contracts c
JOIN bens b ON c.ben_id = b.id
WHERE :YearMonth = to_char(c.date,'YYYYMM') AND NOT c.approved = 'REJECTED'
GROUP BY c.date, c.approved
ORDER BY c.date
I have this SQL in a method that passes a DataSet to the ObjectDataSource in the .aspx page (The approved field can have 3 values: REJECTED, APPROVED and PENDING).
Chart in .aspx page:
<asp:Chart ID="Chart1" runat="server" DataSourceID="RelatorioDataSource"
Width="700px" Compression="10" Palette="Chocolate">
<Series>
<asp:Series Name="Contracts" XValueMember="date"
YValueMembers="amt_c" IsXValueIndexed="False"
XValueType="DateTime" IsValueShownAsLabel="True" BorderDashStyle="DashDot"
CustomProperties="DrawingStyle=Emboss, EmptyPointValue=Zero, DrawSideBySide=True"
YValuesPerPoint="4">
</asp:Series>
<asp:Series BorderDashStyle="DashDot" ChartArea="ChartArea1"
CustomProperties="DrawingStyle=Emboss, EmptyPointValue=Zero, DrawSideBySide=True"
IsValueShownAsLabel="True" Name="Bens"
XValueMember="date" XValueType="DateTime"
YValueMembers="amt_b" YValuesPerPoint="4">
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
I want to show the numbers of approved/pending contracts/bens for each day (4 bars), but the chart shows only two columns.
Solved by creating an object relatorio to hold the returned data (instead of the DataSet), filtering the results using LINQ to Objects, and adding the series programmatically in codeBehind.
var approved = relatorio
.Where(r => r.APPROVED == "APPROVED")
.ToList()
;
var pending = relatorio
.Where(r => r.APPROVED == "PENDING")
.ToList()
;
Creating Legends
Legend legenda = new Legend("Legenda");
legenda.Docking = Docking.Bottom;
legenda.LegendStyle = LegendStyle.Row;
legenda.Alignment = System.Drawing.StringAlignment.Center;
Creating series in a loop
for (int i = 0; i < 4; i++) {
Series temp = new Series {
XAxisType = AxisType.Primary,
XValueType = ChartValueType.DateTime,
YAxisType = AxisType.Primary,
//mostra só a quantidade de contratos
IsValueShownAsLabel = i % 2 == 0 ? true : false,
ChartType = SeriesChartType.Column,
CustomProperties = "EmptyPointValue=Zero",
Legend = "Legenda"
};
grafico.Series.Add(temp);
}
approvedValues.Points.DataBindXY(approved, "DATE", approved, "SUM_VALUES");
DataBinding series
// approved CONTRACTS
grafico.Series[0].Points.DataBindXY(approved, "DATE", approved, "AMT_C");
grafico.Series[0].LegendText = "Contratos approved";
// approved BENS
grafico.Series[1].Points.DataBindXY(approved, "DATE", approved, "AMT_B");
grafico.Series[1].LegendText = "Ben approved";
grafico.Series[1].ChartType = SeriesChartType.Line;
// pending CONTRACTS
grafico.Series[2].Points.DataBindXY(pending, "DATE", pending, "AMT_C");
grafico.Series[2].LegendText = "Contratos pending";
// pending BENS
grafico.Series[3].Points.DataBindXY(pending, "DATE", pending, "AMT_B");
grafico.Series[3].LegendText = "Ben pending";
grafico.Series[3].ChartType = SeriesChartType.Line;
Create a group for each series..
example:
chart1.series[0]["StackedGroupName"] = "group1";
I have a chart control that works normally for all but one case.
If I select a date range of 1 day, (7/27/2011 to 7/28/2011) or anything greater I see the trend line and can adjust the layout and formatting of the labels accordingly.
If I select one day (7/27/2011 - 7/27/2011) I see the series show up in the legend and the y-axis scales appropriately but no trend line is shown.
Each day has 144 datapoints and when I select one day of data I see 144 points come across if I export data from the chart into an XML file or put up a message box when I am building my series. I see the same results if I select multiple days, with the appropriate amount of days included.
I have datapoints every 10 minutes during each day and if I display a messagebox with the values that are being added to the series I see data when I am looking at the single day range so I assume that I should be seeing a trend line.
What am I missing here?
Here is the code for the chart:
<asp:chart id="Chart1" runat="server" Height="365px"
Width="700px" ImageLocation="~/TempImages/ChartPic_#SEQ(300,3)" ImageType="Png"
BackColor="WhiteSmoke" BackSecondaryColor="White" BackGradientStyle="TopBottom"
palette="BrightPastel" BorderWidth="2"
BorderColor="26, 59, 105">
<titles>
<asp:Title ShadowColor="32, 0, 0, 0" Font="Trebuchet MS, 14.25pt, style=Bold" ShadowOffset="3" Text="Chart Title" Alignment="MiddleLeft" ForeColor="26, 59, 105"></asp:Title>
</titles>
<legends>
<asp:Legend Enabled="True" IsTextAutoFit="False" Name="Default" BackColor="Transparent" Font="Trebuchet MS, 8.25pt, style=Bold"></asp:Legend>
</legends>
<borderskin skinstyle="Emboss"></borderskin>
<chartareas>
<asp:ChartArea Name="ChartArea1" BorderColor="64, 64, 64, 64" BorderDashStyle="Solid" BackSecondaryColor="White" BackColor="Gainsboro" ShadowColor="Transparent" BackGradientStyle="TopBottom">
<axisy2 enabled="False"></axisy2>
<axisx2 enabled="False"></axisx2>
<area3dstyle Rotation="10" perspective="10" Inclination="15" IsRightAngleAxes="False" wallwidth="0" IsClustered="False"></area3dstyle>
<axisy linecolor="64, 64, 64, 64" IsLabelAutoFit="False" ArrowStyle="Triangle">
<labelstyle font="Trebuchet MS, 8.25pt, style=Bold" />
<majorgrid linecolor="64, 64, 64, 64" />
</axisy>
<axisx linecolor="64, 64, 64, 64" IsLabelAutoFit="False" ArrowStyle="Triangle">
<labelstyle font="Trebuchet MS, 8.25pt, style=Bold" IsStaggered="False"/>
<majorgrid linecolor="64, 64, 64, 64" />
</axisx>
</asp:ChartArea>
</chartareas>
</asp:chart>
And here is the code I am using to build the series:
foreach (TreeNode node in ChartTreeView.CheckedNodes)
{
if(node.Text.Contains("XXX") )
{
Series series = Chart1.Series.Add(node.Text);
series.ChartArea = "ChartArea1";
series.ChartType = (SeriesChartType)Enum.Parse(typeof(SeriesChartType), charts[1], true);
SqlConnection sqlConnection = new SqlConnection(#"DATA GOES HERE FOR SQL");
sqlConnection.Open();
SqlCommand nodeQuery = new SqlCommand();
nodeQuery.CommandText = "";
if (node.Text.Contains("XXX"))
{
nodeQuery.CommandText = "SELECT (Date + CONVERT(datetime,Time)) As TimeStamp, (MW + kW) As Energy, [EquipmentID] FROM EquipmentData WHERE [EquipmentID] = '" + node.Text + "' AND (Date + CONVERT(datetime,Time)) BETWEEN '" + startDateFilter + "' AND '" + endDateFilter + "' and [SiteID] = "+ProjectNavigation.SelectedValue.ToString()+" ORDER BY TimeStamp";";
nodeQuery.Connection = sqlConnection;
}
if (nodeQuery.CommandText != "")
{
SqlDataReader reader = nodeQuery.ExecuteReader();
while (reader.Read())
{
double value = (double)reader["Energy"];
DateTime TimeStamp = (DateTime)reader["TimeStamp"];
string equipID = (string)reader["EquipmentID"];
series.Points.AddXY(TimeStamp, value);
}
sqlConnection.Close();
}
}
}
Chart1.DataBind();
I don't have an interval set in the .aspx file, but I looked through the chart samples provided for the charts and have tried using the following function to set the interval ranges:
public void SetAxisInterval(System.Web.UI.DataVisualization.Charting.Axis axis, double interval, DateTimeIntervalType intervalType)
{
SetAxisInterval(axis, interval, intervalType, 0, DateTimeIntervalType.Auto);
}
public void SetAxisInterval(System.Web.UI.DataVisualization.Charting.Axis axis, double interval, DateTimeIntervalType intervalType, double intervalOffset, DateTimeIntervalType intervalOffsetType)
{
// Set interval-related properties
axis.Interval = interval;
axis.IntervalType = intervalType;
axis.IntervalOffset = intervalOffset;
axis.IntervalOffsetType = intervalOffsetType;
}
Calling it with the following for the case where the range of days is 0 days:
SetAxisInterval(Chart1.ChartAreas["ChartArea1"].AxisX, 10, DateTimeIntervalType.Minutes);
The problem was in setting the minimum and maximum values for the X-axis on the chart.
I had been setting the minimum and maximum to the start and end date which was not displaying data.
DateTime startDateVal;
DateTime endDateVal;
TimeSpan span = DateTime.Parse(endDate.Text) - DateTime.Parse(startDate.Text);
if (span.TotalDays > 0)
{
startDateVal = DateTime.Parse(startDate.Text);
endDateVal = DateTime.Parse(endDate.Text;
}
else
{
startDateVal = DateTime.Parse(startDate.Text);
endDateVal = DateTime.Parse(endDate.Text).AddDays(1);
}
Chart1.ChartAreas["ChartArea1"].AxisX.Minimum = startDateVal.ToOADate();
Char1t.ChartAreas["ChartArea1"].AxisX.Maximum = endDateVal.ToOADate();
Using the code above to force the maximum to be midnight the day after the currently selected day fixed the problem.