I'm writing a reusable control - lets call it MyListView - inherited from standard ASP.NET ListView control. It's datasource is always set to a LinqDataSource and I need to calculate total value for a specific column (sum of all values for that column). Which way is the best to calculate a total value? I was thinking of OnItemDataBound event and computing total there using global variable, but I also need paging in MyListView (using standard Pager control) and this event is fired only for rows on currently visible page, not for all rows in the datasource. I also don't want to calculate total sum in code behind of ASPX page, I want to just specify a column name in aspx, and MyListView will automatically compute total value for the column.
Thank you for help!
IF you're using pagination it's not easy to have that result. I think you should consider to put the row used for totals outside the ListView (so you can use LINQ to compute totals too, I guess you don't want to enumerate all items to compute a total when it can be done quickly on SQL side).
Dim total As Integer
For Each Items As ListViewItem In lV_allItems.Items
Dim lbl As Label = CType(Items.FindControl("Quantitytxtbox"), Label)
total += lbl.Text
Next
Label1.Text = "TOTAL FRAME ADDED : " + total.ToString
I put this code in the page prerender and it works just fine, you have to make sure what is in the columns is an integer otherwise you need to convert.
If you want to get total value from database my suggession is to pass an output parameter with you query / linkq to the database and get the sum of all records from database in the same call in which you get data.
assume you use this query to bind you listview
var queryforBind= (from c in table).Skip(1).Take(10); //1 and 10 can be changed according to your requirement
and after bind your list view call this query to compute total.
var sum = queryforBind.Sum(x => x => x.Field); //Field can be according your requirement
Related
I am trying to populate records on a gridview depending on the result of two linq methods:
GetRecords(string SearchCriteria, int skip, int take)
which provides me the ammount of rows i´m going to show into the gridview, and
CountRecords(string SearchCriteria)
Which provides me with the total count of the records.
First I get the number of records by using the CountRecords method, and then I calculate the number of pages to make the user know how many pages the gridview has, but the property gridview.PageCount is read only. How can i set the ammount of pages the gridview is going to have, without getting all the records (they're about 300000, so i cannot afford this option)?
Set virtual count. Set AllowCustomPaging to true.
http://msdn.microsoft.com/en-us/library/zxdbyxtc.aspx
The Setup:
I currently have a page with a GridView control on it inside of an update panel, using a SqlDataSource. I have a timer setup to update the GridView every X amount of seconds. Typically for what I am testing every time the GridView updates about 4-5 new rows of data are added to the gridview, while the last 4-5 get tossed out. I am only displaying 15 results at a time and will have new results coming in every update.
The Problem:
I allow the user to select the rows, while the GridView is being updated. I am handling this by setting the SelectedIndex property. However, when I select a row and then the grid is updated the row the user selected gets pushed down about 4-5 rows and the data in the previous selected index is selected instead. So where they clicked is selected at this point, not what they clicked.
I need a way to determine, if possible from the SqlDataSource/Gridview, how many new rows have been added to the gridview. OR a way to maintain the selected data by the data in the row and not just the SelectedIndex.
Any help is appreciated, thanks.
RESOLVED:
Ok I went ahead and added a new invisible column to my grid, and am now keep track of the unique ID's selected from the DB. By setting an array before databinding, and comparing that to the new array I get after databinding I was able to use a simple Intersect to determine the number of rows that are the same. Then I used that to determine from the total how many are new this postback.
Just an idea:
I think you can use an invisible column (more specifically an ID column) to store the selected rows' IDs value in the Session object and then after the grid updates, you can retrieve this value(s) and select the row(s) again if they are still present.
If you have custom GridView OnRowUpdating event.
public void GridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
Session["CurrIndex"] = GridView.SelectedIndex;//index before insertion
Session["RowCount"] = GridView.Rows.Count;//row count before insertion
//Add new Rows
GridView.SelectedIndex = (Int32)(Session["CurrIndex"]) + ( GridView.Rows.Count - (Int32)(Session["RowCount"]);//update selected index
Session["CurrIndex"] = GridView.SelectedIndex;//restore the index into session
}
I have a gridview that shows, for example, a baseball team's statistics. It's a standard sports stats grid - the rows show statistics for each player and the columns show the specific stat for the each player.
Easy enough so far. But what I would then like to do is style (highlight or bold) the Max or Min (the team leader) of each stat column. For example, Player A may only lead in one or two categories, so we cannot style the entire row. If Player A just leads the team in strikeouts, I just want to style the number of strikeouts he had (THAT cell only).
What's the best way to handle this? Make SQL Server do all the work and in effect, rank EVERY stat of each player, effectively doubling the number of columns (e.g. col: AB, col: ABRank). Or do I let the rowdatabound event of the gridview handle this?
If I chose the latter, I think I would get the Max of every statistical category from the datatable before binding (e.g. store them in a local variable) then on rowdatabound, if they match the value, apply the style.
You already gave the answer to your own question, which is by the way the answer I'd have given you.
Or do I let the rowdatabound event of
the gridview handle this?
If I chose the latter, I think I would
get the Max of every statistical
category from the datatable before
binding (e.g. store them in a local
variable) then on rowdatabound, if
they match the value, apply the style.
There is an option you didn't mention. You could use javascript clientside to do the highlighting. should be rather simple to run over a table am highlight the highest values in a column.
Depending on what you are doing you probably have a certain amount of columns you bind to.
I would use LINQ on your DataSource, before you bind it, for each type you want the max for example:
// create a global variable to hold the data
int _maxHomeRuns = 0;
// Then before you bind the datasource, find out the max of each stat
_maxHomeRuns = baseballStats.Max(i => i.HomeRuns); // get the max
// Then in your template columns Label control DataBinding method
if ((int)(Eval("HomeRuns")) == _maxHomeRuns)
{
// Assign the style you want
((Label)(sender)).CssClass = "MaxCellStyle";
}
I wouldn't use the RowDataBinding, do it at the control level's OnDataBinding so you are scoping the checks specifically to a control so you don't have to search for controls on a row.
Without paging function, i can loop through the gridview by using
var sum = 0;
var gridViewCtlId = '<%=timesheetView.ClientID%>';
var grid = document.getElementById(gridViewCtlId);
var gridLength = grid.rows.length;
so with gridLength i can loop through the gridview to sum all rows. However, when I use paging event of gridview, i use the page size to loop through all rows, but it occurs errors because the last page may not have enough rows. So would you please to help me how to get the rows in the each page of gridview?
What you have is correct, just update the gridLength property just before calculating the sum. There's no way for javascript to know the number of rows until the grid is there and present on the page...but that's what you're doing already, so just update that row count.
The only way I picture what you currently have not working is you have this code running initially and not when an UpdatePanel (or other loading mechanism) comes back, just re-grabbing the gridLength will resolve this, as the updated <table> in the DOM will have the correct number of rows.
In your loop, you can do a check like this
if (grid.rows[rowIndex]){
// Your code to calculate sum goes here
}
I'm populating a Telerik RadGrid with data from a DataTable (System.Data.DataTable). As I'm supporting someone else's application, I can't use any other data source or display control.
In my grid I have three columns: let's say they are Widgets Produced (column A), Faulty Widgets (column B) and Faultiness Proportion (column C). The database query provides these for me and does the calculation C = B / A.
I have a totals row (a Telerik GridFooterItem) at the bottom of the grid. In columns A and B Telerik calculates the totals for those columns for me. We can't calculate the correct value for the 'total' of column C from column C alone: we have to populate it with (the sum of B) / (the sum of A).
I've managed to do this by handling the DataBound event of the RadGrid and manually populating the cells in the footer. (I had to catch the GridFooterItem in the ItemCreated event, then put values in it in the DataBound event, after it had automatically calculated the totals for A and B for me.) This feels pretty hacky - maybe there's a better way...?
Anyway, the important bit is this:
My grid is split into groups so I also need to populate column C in the GridGroupFooterItems. I can't get my hacky technique to work in this case: I'm finding the footer cell I want with myGridFooterItem["WidgetsProduced"], but I can't get the group footer cells with myGridGroupFooterItem["WidgetsProduced"] - it just isn't a dictionary.
I've tried using myGridGroupFooterItem.Cells[], but this TableCellCollection contains a couple more cells than I'd expect, so accessing them by integer index feels a tad ropey (especially as this is a user-defined report, so the columns may be in any order).
So: how do I populate these cells with my calculation?
your item databound event looks something like
grd_ItemDataBound(object sender,GridItemEventArgs e)
{
//catch the footer element
if(e.Item.ItemType==GridItemType.GroupFooter)
{
(e.Item.FindControl("yourTextBox") as TextBox).Text = your calculated value
}
}
I double-checked whether unique name indexer works with Q2 2009 and Q3 2009 version of RadGrid for ASP.NET AJAX and it worked on my machine. Check your version and ask for more help using the Telerik forums if needed.
Dick
Try this
In Aspx page:
<telerik:GridBoundColumn Aggregate="Sum" DataField="Price" DataFormatString="{0:C}" EmptyDataText="0" FooterText="Total :" HeaderText="Price" UniqueName="Price"> ...
(Or)
In Code behind page:
Private Sub RadGrid1_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemDataBound
Dim Item As GridDataItem
Dim value as Double
Select Case (e.Item.ItemType)
Case Telerik.Web.UI.GridItemType.AlternatingItem, Telerik.Web.UI.GridItemType.EditItem,Telerik.Web.UI.GridItemType.Item,Telerik.Web.UI.GridItemType.SelectedItem
Item = e.Item
'------ Calculate Total amount -----------
Item("TotalPayment").Text = CDbl(Item("TotalPayment").Text)
value += CDec(Item("TotalPayment").Text)
Case Telerik.Web.UI.GridItemType.Footer
'------ Display the total amount in Footer ------
Dim footerItem As GridFooterItem = e.Item
If Not RadGrid1.Items.Count = 0 Then footerItem("TotalPayment").Text = "Total :" + value
End Select
End Sub
Well, if you use custom formula to calculate results instead of standard aggregates like sum, average and so on, you probably have to rely on your own logic. The cells from the group footers should be indexable by unique name - I remember this was not supported with previous Telerik ASP.NET Grid versions but this was added in more recent versions - Q2 or Q3 2009.
Dick