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;
Related
I have got following dataset which is returned by SQL Server:
Group Name Month Total ORDER
Group-India Apr 80
Group-US Apr 70
Group-Europe Apr 60
Group-India May 82
Group-US May 85
Group-Europe May 89
ASP.Net Charts - I need to display this CHART by MONTH (means Apr will be one series and MAY will be separate series) and Y-axis should be GROUPNAME (and show count for it).
Please help
Regards
use DataBindCrossTable
Sample class
public class Sample
{
public string groupName { get; set; }
public string month { get; set; }
public int totalOrder { get; set; }
}
.aspx
<asp:Chart ID="Chart1" runat="server" Width="600px">
<Legends>
<asp:Legend TitleFont="Microsoft Sans Serif, 8pt, style=Bold" BackColor="Transparent" Font="Trebuchet MS, 8.25pt, style=Bold" IsTextAutoFit="False" Enabled="True" Name="Default"></asp:Legend>
</Legends>
<Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
code behind (.aspx.cs)
var sampleData =
new List<Sample> {
new Sample { month = "apr", groupName = "Group-India", totalOrder = 50 },
new Sample { month = "apr", groupName = "Group-US", totalOrder = 500 },
new Sample { month = "apr", groupName = "Group-Europe", totalOrder = 151 },
new Sample { month = "May", groupName = "Group-India", totalOrder = 15 },
new Sample { month = "May", groupName = "Group-US", totalOrder = 150 },
new Sample { month = "May", groupName = "Group-Europe", totalOrder = 1500}
};
// data bind
Chart1.DataBindCrossTable(sampleData, "groupName", "month", "totalOrder", "Label=totalOrder");
and here's the output
If you don't want to write a class for mapping, then you can directly convert a data table to Enumerable() as follow.
List<DataRow> list = dt.AsEnumerable().ToList();
Something like this
using (con = new SqlConnection(cs))
{
com = new SqlCommand("ERPM_Learnar_Info_By_Gender", con);
com.CommandType = CommandType.StoredProcedure;
adapt = new SqlDataAdapter(com);
dt = new DataTable();
adapt.Fill(dt);
List<DataRow> list = dt.AsEnumerable().ToList();
Chart1.DataBindCrossTable(list, "Gender_Name", "District_Name", "Total", "Label=Total");
and the result is
stored procedure result was this
I have a page in my asp.net project where I want to show the attendance of the employees. When present P should be shown and when absent then A and on holidays H should be shown in the repeater. Now on my web page I have 2 textboxes through which I enter the year and the month and for that month I want to get the attendance. My database tables are as follows.
(1) Calender
CalederID Year Month WorkingDays
1 2013 January 1111001111100111110011111001111
2 2013 February 1001111100111110011111001111
and so on . Here 1 represent the working days in the month and 0's are Saturday's and Sunday's
am using this pattern because on one of my page am getting checkboxes checked for (sat and sun) and unchecked for others so I know that these are holidays
(2) Attendance Table
AttendanceID EmpID PresentDays CalenderID LeaveDate
1 1 Null 1 2013-01-14
2 1 Null 2 2013-02-15
3 1 Null 4 2013-04-11
4 3 Null 6 2013-06-26
(3) EmpInfo Table
EmpID EmpName and so on
1 Joe
2 Sandra
Now coming to the problem on my web page when I enter the year and month I want to show the repeater with headers as Date Numbers which represent the dates of that month. Now if the month has 30 days then 30 numbers are shown. Another repeater is used which has to show the attendance in the format P,A,H as told above
My Repeaters look like this
<table class="table1" >
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<tr>
<td>Employee ID</td>
</HeaderTemplate>
<ItemTemplate>
<td><asp:Label ID="lbldates" runat="server" Text='<%# Eval("Dates") %>' ></asp:Label></td>
</ItemTemplate>
<FooterTemplate>
<td>TOTAL</td></tr>
<tr>
</FooterTemplate>
</asp:Repeater>
<asp:Repeater id="rptAttendance" runat="server" OnItemDataBound="rptAttendance_ItemDataBound">
<ItemTemplate>
<tr>
<td><asp:Label ID="lblEmpName" runat="server" /></td>
<asp:Repeater ID="rptAttendanceCode" runat="server" OnItemDataBound="rptAttendanceCode_ItemDataBound" >
<ItemTemplate><td><asp:Label ID="lblAttendanceCode" runat="server" /></td></ItemTemplate>
</asp:Repeater>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
and the code behind is
protected void Page_Load(object sender, EventArgs e)
{
}
public void search(object sender, EventArgs e)
{
string cnnString = "Server=localhost;Port=3307;Database=leavesystem;Uid=root;Pwd=ashish";
MySqlConnection cnx = new MySqlConnection(cnnString);
cnx.Open();
string cmdText1 = "SELECT DAY(LAST_DAY(CAST(CONCAT('" + year.Value + "', '-', MONTH(STR_TO_DATE('" + month.Value + "', '%M')), '-', 1) AS DATE))) ";
MySqlCommand cmd1 = new MySqlCommand(cmdText1, cnx);
MySqlDataAdapter adapter1 = new MySqlDataAdapter();
DataSet ds1 = new DataSet();
adapter1.SelectCommand = cmd1;
adapter1.Fill(ds1);
DataRow dr;
dr = ds1.Tables[0].Rows[0];
string value = dr[0].ToString();
string cmdText2 = "SELECT Dates from temp where Dates <= " + value + " ";
MySqlCommand cmd2 = new MySqlCommand(cmdText2, cnx);
MySqlDataAdapter adapter2 = new MySqlDataAdapter();
DataSet ds2 = new DataSet();
adapter2.SelectCommand = cmd2;
adapter2.Fill(ds2);
DataTable dt = ds2.Tables[0];
Repeater1.DataSource = dt;
Repeater1.DataBind();
string cmdText3 = "SELECT CalenderID, WorkingDays from calender where Year = '" + year.Value + "' and Month = '" + month.Value + "' ";
MySqlCommand cmd3 = new MySqlCommand(cmdText3, cnx);
MySqlDataAdapter adapter3 = new MySqlDataAdapter();
DataSet ds3 = new DataSet();
adapter3.SelectCommand = cmd3;
adapter3.Fill(ds3);
DataTable calender = ds3.Tables[0];
DataRow dr3;
dr3 = ds3.Tables[0].Rows[0];
string CalenderID = dr3[0].ToString();
string cmdText4 = "SELECT EmpID,EmpName from empinfo ";
MySqlCommand cmd4 = new MySqlCommand(cmdText4, cnx);
MySqlDataAdapter adapter4 = new MySqlDataAdapter();
DataSet ds4 = new DataSet();
adapter4.SelectCommand = cmd4;
adapter4.Fill(ds4);
DataTable employees = ds4.Tables[0];
string cmdText5 = "SELECT EmpID,DAY(LeaveDate) AS LeaveDayOfMonth from attendance where CalenderID = '" + CalenderID + "' ";
MySqlCommand cmd5 = new MySqlCommand(cmdText5, cnx);
MySqlDataAdapter adapter5 = new MySqlDataAdapter();
DataSet ds5 = new DataSet();
adapter5.SelectCommand = cmd5;
adapter5.Fill(ds5);
DataTable attendance = ds5.Tables[0];
List<Tuple<string, string[]>> info = new List<Tuple<string, string[]>>();
int calendarID = calender.Rows[0].Field<int>("CalenderID");
string days = calender.Rows[0].Field<string>("WorkingDays");
days = days.Replace("1", "P");
days = days.Replace("0", "H");
string[] daysList = days.Select(d => d.ToString()).ToArray();
int present = 0;
int holidays = 0;
for (int i = 0; i < daysList.Length; ++i)
{
if (daysList[i] == "P")
present++;
if (daysList[i] == "H")
holidays++;
}
int working = (monthdays - holidays);
string total = (present + "/" + working);
Tuple<string, string[],string> employeeAttendance = null;
foreach (DataRow employee in employees.Rows)
{
employeeAttendance = new Tuple<string, string[],string>(employee.Field<string>("EmpName"), daysList,total);
foreach (DataRow absentDay in attendance.AsEnumerable().Where(a => a.Field<int>("EmpID") == employee.Field<int>("EmpID")))
{
var leaveDay = absentDay.Field<Int64>("LeaveDayOfMonth");
int leaveDay1 = Convert.ToInt16(leaveDay);
leaveDay1 = leaveDay1 - 1;
employeeAttendance.Item2[leaveDay1] = "A";
}
info.Add(employeeAttendance);
}
this.rptAttendance.DataSource = info;
this.rptAttendance.DataBind();
}
protected void rptAttendance_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Tuple<string, string[],string> info = (Tuple<string, string[],string>)e.Item.DataItem;
((Label)e.Item.FindControl("lblEmpName")).Text = info.Item1;
((Label)e.Item.FindControl("lbltotal")).Text = info.Item3;
Repeater attendanceCode = (Repeater)e.Item.FindControl("rptAttendanceCode");
attendanceCode.DataSource = info.Item2;
attendanceCode.DataBind();
}
}
protected void rptAttendanceCode_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
((Label)e.Item.FindControl("lblAttendanceCode")).Text = e.Item.DataItem.ToString();
}
}
In code behind I get the number of days in the month then compare it with a table which has 31 dates and from that logic I dsplay my numbers and on the bottom left using repeater 2 to show my EmpID's and now beside them below the date numbers I want to show the attendance. Can some one tell me how to do this. The PresendtDays columns in my attendance table is empty but I dont know how to use that. Please help me out I have been trying this from many hours and that is why I posted my complete code so that some one would help me. Looking for an early response. Thanks in advance !!
Due to the unconventional design of your database, I had to do some major data manipulation to make this work. That being said, here is my proposed solution.
Instead of the SQL statement "SELECT EmpID from empinfo ", you will need to perform three additional queries:
Retrieve info from the Calendar table:
SELECT CalendarID, WorkingDays FROM Calendar WHERE Year = [YEAR] and Month = [MONTH]
This will return a table that looks like this:
Retrieve info from the Calendar table using the CalendarID:
SELECT EmpID, EmpName FROM Employees
This will return a table that looks like this:
Retrieve info from Attendance table, using the CalendarID from the first query.
SELECT EmpID, DAY(LeaveDate) AS LeaveDayOfMonth FROM Attendance WHERE CalendarID = [CALENDAR ID]
This will return a table that looks like this:
Once you have done this, replace your second repeater (Repeater2) with the following TWO repeaters. The, first repeater (rptAttendance) lists each employee, the second repeater (rptAttendanceCode) list each day of the month for the employee. (Note, we are connecting to the repeaters's OnItemDataBound event, more on this later):
<asp:Repeater id="rptAttendance" runat="server" OnItemDataBound="rptAttendance_ItemDataBound">
<ItemTemplate>
<tr>
<td><asp:Label ID="lblEmpName" runat="server" /></td>
<asp:Repeater ID="rptAttendanceCode" runat="server" OnItemDataBound="rptAttendanceCode_ItemDataBound" >
<ItemTemplate><td><asp:Label ID="lblAttendanceCode" runat="server" /></td></ItemTemplate>
</asp:Repeater>
</tr>
</ItemTemplate>
</asp:Repeater>
Now, this is where the fun starts!
First, you need to create a data structure that hold the employee name and his/her attendance for each day of the month. We will use the WorkingDays field for our base line and append it with each employee's attendance (taken from the Attendance table).
//This list (info) holds the employee's name in the first string, and their attendance in the string array
List<Tuple<string, string[]>> info = new List<Tuple<string, string[]>>();
int calendarID = calendar.Rows[0].Field<int>("CalendarID");
string days = calendar.Rows[0].Field<string>("WorkingDays");
Replace the day-type code with the corresponding letter
days = days.Replace("1", "P");
days = days.Replace("0", "H");
Convert this into an an array so we can iterate over it
string[] daysList = days.Select(d => d.ToString()).ToArray();
Now we will iterate over each employee record and create a data structure for each employee. Then we will iterate over each employee's day off and update their daylist collection with the days that they were not at work.
foreach (DataRow employee in employees.Rows)
{
employeeAttendance = new Tuple<string, string[]>(employee.Field<string>("EmpName"), daysList);
foreach (DataRow absentDay in attendance.AsEnumerable().Where(a => a.Field<int>("EmpID") == employee.Field<int>("EmpID")))
{
employeeAttendance.Item2[absentDay.Field<int>("LeaveDayOfMonth") - 1] = "A";
}
info.Add(employeeAttendance);
}
Here are each repeater's ItemDataBound event handlers:
protected void rptAttendance_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Tuple<string, string[]> info = (Tuple<string, string[]>)e.Item.DataItem;
((Label)e.Item.FindControl("lblEmpName")).Text = info.Item1;
Repeater attendanceCode = (Repeater)e.Item.FindControl("rptAttendanceCode");
attendanceCode.DataSource = info.Item2;
attendanceCode.DataBind();
}
}
protected void rptAttendanceCode_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
((Label)e.Item.FindControl("lblAttendanceCode")).Text = e.Item.DataItem.ToString();
}
}
Here is the code-behind in its entirety:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
List<Tuple<string, string[]>> info = new List<Tuple<string, string[]>>();
int calendarID = calendar.Rows[0].Field<int>("CalendarID");
string days = calendar.Rows[0].Field<string>("WorkingDays");
days = days.Replace("1", "P");
days = days.Replace("0", "H");
string[] daysList = days.Select(d => d.ToString()).ToArray();
Tuple<string, string[]> employeeAttendance = null;
foreach (DataRow employee in employees.Rows)
{
employeeAttendance = new Tuple<string, string[]>(employee.Field<string>("EmpName"), daysList);
foreach (DataRow absentDay in attendance.AsEnumerable().Where(a => a.Field<int>("EmpID") == employee.Field<int>("EmpID")))
{
employeeAttendance.Item2[absentDay.Field<int>("LeaveDayOfMonth") - 1] = "A";
}
info.Add(employeeAttendance);
}
this.rptAttendance.DataSource = info;
this.rptAttendance.DataBind();
}
}
protected void rptAttendance_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Tuple<string, string[]> info = (Tuple<string, string[]>)e.Item.DataItem;
((Label)e.Item.FindControl("lblEmpName")).Text = info.Item1;
Repeater attendanceCode = (Repeater)e.Item.FindControl("rptAttendanceCode");
attendanceCode.DataSource = info.Item2;
attendanceCode.DataBind();
}
}
protected void rptAttendanceCode_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
((Label)e.Item.FindControl("lblAttendanceCode")).Text = e.Item.DataItem.ToString();
}
}
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'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"
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.