Click here to Skip to main content
15,894,896 members
Articles / Web Development / ASP.NET

Race to Linux - Race 3: Reports Starter Kit using Mono SqlServer/Firebird

Rate me:
Please Sign up or sign in to vote.
2.33/5 (2 votes)
30 Sep 20052 min read 53.1K   328   15  
Reports Starter Kit port to Linux using Mono
<html>
	<head>
		<title>ASP.NET Reports Starter Kit Documentation</title><link href="style.css" type="text/css" rel="stylesheet"></head>
	<body class="NormalIndent">
		<h1>HierarchicalReport
		</h1>
		<p><b>Description:</b> &nbsp;&nbsp;&nbsp;The&nbsp;hierarchical report displays 3 
			different grids.&nbsp; The first grid displays sales totals, grouped by 
			territory, and filtered by year. The second grid displays sales totals grouped 
			by employee, within a&nbsp;specific territory - namely, the territory selected 
			in the first grid.&nbsp; The third grid shows&nbsp;information&nbsp;on a 
			particular employee - namely, the employee selected in the second grid.
		</p>
		<p><strong>Overview:</strong> &nbsp;&nbsp;&nbsp;&nbsp;Three DataGrids are set up on 
			this page, each with their own data source, retrieved from three separate 
			stored procedures.&nbsp; Only the data source for the first grid,&nbsp;"Sales 
			By Territory" is bound at Page Load and does not change; the other 2 grids are 
			hidden until the user selects the Territory, and then the Employee.&nbsp; When 
			the user chooses which Territory to view, the second grid, "Sales for&nbsp;[<em>Territory</em>]" 
			becomes visible, and is bound to the results of the stored procedure 
			"GetEmployeeSalesByTerritory", which accepts the Territory Name&nbsp;as a 
			parameter.&nbsp; Similarly, when the user chooses which Employee to view, the 
			third grid, "Employee Info for [<em>Employee</em> ]" becomes visible, and is 
			bound to the results of the stored procedure "GetEmployeeByID", which accepts 
			the Employee's ID as a parameter.&nbsp; Should the user click on the Territory 
			grid&nbsp;when the Employee grid&nbsp;is visible, the Employee grid will hide, 
			and the Employee Sales by Territory grid&nbsp;will refresh with the new data.
		</p>
		<p>Additionally, this report demonstrates how to implement interactive sorting and 
			paging&nbsp;using ASP.NET.
		</p>
		<p>
			Sorting is enabled for each column in the first two DataGrids. The sortable 
			columns can be sorted in ascending or descending order. Sortable columns are 
			displayed as red and underlined when the user hovers over the column header.
		</p>
		<p><img src="./images/1x1.gif" width="25"><img src="./images/hierarchicalsorting.gif"></p>
		<p>Paging is also enabled&nbsp;in the first two DataGrids, so that a limited number 
			of records can be displayed on each page, with the ability to navigate through 
			the pages of data.&nbsp; Links to previous and next pages are 
			displayed&nbsp;just above the footer section of the DataGrids.&nbsp; In the 
			footer section, below the&nbsp;navigation links, a text field shows how many 
			pages total there are, as well as which page&nbsp;the user is on.&nbsp;</p>
		<p><img src="./images/1x1.gif" width="25"><img src="./images/hierarchicalpaging.gif"> 
			&nbsp;
			<br>
		</p>
		<p><strong>Implementation Notes:&nbsp;</strong> &nbsp;&nbsp;
		</p>
		<p>In order for the user to be able to make a selection from one of the grids, and 
			to be able to pass that information to the codebehind, a Template column is 
			used as&nbsp;the first column in the top two DataGrids.&nbsp; A Template 
			column&nbsp;is used&nbsp;to create a column with a customized control layout, 
			including custom appearances for the heading section, the footer section, and 
			the items section of the column. In this example,&nbsp;a LinkButton&nbsp;within 
			the DataGrid Template column&nbsp;captures the user input - namely, the 
			Territory&nbsp;or Employee&nbsp;selected.</p>
		<pre>	&lt;<font color=blue>asp:templatecolumn</font> sortexpression="Territory" headertext="Territory Name"&gt;
	    &lt;itemtemplate&gt;
	        &lt;asp:linkbutton <font color=blue>oncommand="TerritoryGrid_Click" commandname="TerritoryDrill" 
				commandargument='&lt;%# DataBinder.Eval(Container, "DataItem.TerritoryDescription") %&gt;'</font> 
				cssclass="hier" runat="server" id="Territorylnk" 
				text='&lt;%# DataBinder.Eval(Container, "DataItem.TerritoryDescription") %&gt;'
	        &lt;/asp:linkbutton&gt;
	    &lt;/itemtemplate&gt;
	    &lt;itemstyle width="200px"&gt;&lt;/itemstyle&gt;
	&lt;/asp:templatecolumn&gt;
		</pre>
		<p>There are three main parts to the implementation of the LinkButton within the 
			Template column: the <em>OnCommand</em> attribute, the <em>CommandName</em> attribute, 
			and the <em>CommandArgument</em> attribute.&nbsp;The OnCommand attribute 
			specifies which method should be run when the LinkButton's text&nbsp;is 
			pressed.&nbsp; The CommandName and CommandArgument attributes hold data that 
			can be passed as parameters to the method.&nbsp; In the above code snippet, the 
			CommandArgument receives the value of the "TerritoryDescription" field of the 
			item selected by the user.&nbsp; The TerritoryGrid_Click method receives this 
			value and passes it to the BindList_EmpTerr method, which is a method that 
			binds the data for the second grid.</p>
		<pre>

	protected void TerritoryGrid_Click(Object sender, CommandEventArgs e)
	{
		string territoryName = e.CommandArgument.ToString().Trim();

		// Put the second grid back to the first page
		EmployeeTerritoryGrid.CurrentPageIndex = 0;

		// Show the table with the second grid, and update the headers
		ETTableColumn.Visible = true;
		ETHeader.Text = territoryName;
		<font color="blue">BindList_EmpTerr(territoryName)</font>;

		// Hide the 3rd table if it was visible
		EmpTableColumn.Visible = false;
	}	
		</pre>
		<p>In the second grid, both the EmployeeID and the EmployeeName are passed into the 
			function ETGrid_Click.&nbsp; The EmployeeName field is used for display in the 
			third grid's Header section, and the EmployeeID field is used to pass in to the 
			BindList_Emp method, which is a method that binds the data for the third grid.</p>
		<pre>    &lt;asp:templatecolumn sortexpression="EmployeeName" headertext="Employee Name"&gt;
	&lt;itemtemplate&gt;
		&lt;asp:linkbutton oncommand="ETGrid_Click" 
				<font color="blue">commandargument='&lt;%# (String) DataBinder.Eval(Container, "DataItem.EmployeeName") + 
				"," + DataBinder.Eval(Container, "DataItem.EmployeeID").ToString() %&gt;'</font>
		cssclass="hier" runat="server" 
		id= "lnkEmployeeTerritory" text='&lt;%# 
		DataBinder.Eval(Container, "DataItem.EmployeeName") %&gt;'&gt; &lt;/asp:linkbutton&gt;
		&lt;/itemtemplate&gt;
	&lt;itemstyle
	width= "150px"&gt;&lt;/itemstyle&gt;
    &lt;/asp:templatecolumn&gt;
		</pre>
		<pre>
		
	protected void ETGrid_Click(Object sender, CommandEventArgs e)
	{
		string[] cmdArgs =  e.CommandArgument.ToString().Split(',');

		string employeeName = cmdArgs[0];
		int employeeID = Convert.ToInt32(cmdArgs[1]);

		// Show the table with the 3rd grid, and update the headers
		EmpTableColumn.Visible = true;
		<font color="blue">EmployeeName.Text = employeeName</font>;
		BindList_Emp(employeeID);			
	}
		</pre>
		<p>
			Binding the data to the top two&nbsp;DataGrids includes&nbsp;four 
			easy&nbsp;steps to account for paging and sorting&nbsp;- retrieving the data, 
			sorting the data, binding the data to the DataGrid's DataSource, and updating 
			the paging text labels.</p>
		<pre>
		
	private void BindList_EmpTerr(string territoryName)
	{
		<font color="blue">HierarchicalReportCollection empTerritoryList = 
			HierarchicalReport.GetEmployeeSalesByTerritory(territoryName)</font>;
		
		// do the sorting if data is returned
		if (empTerritoryList.Count &gt; 0) 
		{
			SortGridData(empTerritoryList, SortField_EmpTerr, SortAscending_EmpTerr);

			EmployeeTerritoryGrid.DataSource = empTerritoryList;
			EmployeeTerritoryGrid.DataBind();
		}

		// Update paging labels
		CurrPage_EmpTerr.Text = Convert.ToString(EmployeeTerritoryGrid.CurrentPageIndex + 1);
		TotPages_EmpTerr.Text = EmployeeTerritoryGrid.PageCount.ToString();
	}		
		</pre>
		<p>Sorting is a simple task to set up and&nbsp;implement with ASP.NET. The 
			DataGrid's AllowSorting property is set to True and an event handler for the 
			sorting is added to the DataGrid. The event handler then catches the sorting 
			criteria, where it is then used to sort the appropriate DataGrid's column.
		</p>
		<pre>   &lt;asp:datagrid id="TerritoryGrid" runat="server"  ... <FONT color=blue> AllowSorting="True" OnSortCommand="SortGrid_Terr"</FONT> ...&gt;
		</pre>
		<pre>		
	private void SortGridData(<font color=blue>HierarchicalReportCollection list</font>, string sortField, bool asc)
	{
		HierarchicalReportCollection.HierarchicalReportFields sortCol = 
				HierarchicalReportCollection.HierarchicalReportFields.InitValue;

		switch(sortField)
		{
			case "Territory":
				sortCol = HierarchicalReportCollection.HierarchicalReportFields.Territory;
				break;
			case "SalesTotals":
				sortCol = HierarchicalReportCollection.HierarchicalReportFields.SalesTotals;
				break;
			case "EmployeeName":
				sortCol = HierarchicalReportCollection.HierarchicalReportFields.EmployeeName;
				break;
		}

		<font color=blue>list.Sort</font>(sortCol, asc);
	}
		</pre>
		<p>The SortGridData method in the codebehind&nbsp;determines which field to sort 
			on, and passes that value to the Sort method of the 
			HierarchicalReportCollection object.&nbsp; The Sort method in the 
			HierarchicalReportCollection component calls the appropriate IComparer 
			method, which simply compares&nbsp;items in order to sort the list.
		</p>
		<pre>	
	public void <font color=blue>Sort</font>(HierarchicalReportFields sortField, bool isAscending)
	{
		switch (sortField) 
		{
			case HierarchicalReportFields.Territory:
				base.Sort(new TerritoryNameComparer());
				break;
			case HierarchicalReportFields.SalesTotals:
				base.Sort(new SalesTotalsComparer());
				break;
			case HierarchicalReportFields.EmployeeName:
				base.Sort(new EmployeeNameComparer());
				break;
		}

		if (!isAscending) base.Reverse();
	}
		</pre>
		<p>
			Implementing ASP.NET paging is even simpler.&nbsp; The AllowPaging property is 
			set to True, a PageSize is set, and a short&nbsp;event handler is 
			defined.&nbsp; The only thing that typically has to be done in the 
			event&nbsp;handler is to set the DataGrid's CurrentPageIndex to the 
			DataGridPageChangedEventArgs.NewPageIndex, and to re-bind.&nbsp; Here, in 
			addition, the second and third table are hidden when the page is changed.&nbsp;</p>
		<pre>    &lt;asp:datagrid id="TerritoryGrid" runat="server" ... <font color=blue>AllowPaging="True" PageSize="5" OnPageIndexChanged="Page_Terr"</font> ... /&gt;
		</pre>
		<pre>		
	protected void Page_Terr(Object sender,  DataGridPageChangedEventArgs e)
	{
		// Hide the 2nd and 3rd table if they were visible
		ETTableColumn.Visible = false;
		EmpTableColumn.Visible = false;

		<font color=blue>TerritoryGrid.CurrentPageIndex = e.NewPageIndex</font>;
		BindList_Terr();
	}
		</pre>
		<p>Finally,&nbsp;a style can be set for the Previous and Next text labels.</p>
		<pre>    &lt;pagerstyle CssClass="PagerHier" PrevPageText="&amp;lt; Prev" NextPageText="Next &amp;gt;" 
		Height="30px" VerticalAlign="middle"&gt;&lt;/pagerstyle&gt;
		</pre>
	</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Uruguay Uruguay
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions