GridView: Creating groups and summaries with 2 lines of code

GridView has a lot of improvements over the DataGrid but it still lacks some very important features. A recurring requirement not available in the GridView is to create groups and summaries. To create summaries we can easily code the RowDataBound event. Grouping is a more complex task, and involves more coding and debugging. But when we need to combine these two features the things really start to get messy. With this in mind I have implemented the GridViewHelper, as the name suggests, a helper class to aid the creation of groups and summaries.

Online Sample http://www.agrinei.com/gridviewhelper/sample/gridviewhelpersample_en.aspx

DownLoad Source Code : http://www.agrinei.com/gridviewhelper/gridviewhelpersample_en.zip

Origional Post : http://www.agrinei.com/gridviewhelper/gridviewhelper_en.htm

Using the GridViewHelper

Below we will see some GridViewHelper samples. First we show the grid to which the groups and summaries will be created. The sample data comes from Northwind database, with a few modifications:

ShipRegion ShipName OrderId ProductName Quantity UnitPrice ItemTotal
NM Old World Delicatessen 10922 Alice Mutton 15 US$ 39,00 US$ 585,00
NM Old World Delicatessen 10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
NM Old World Delicatessen 10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
NM Old World Delicatessen 10925 Filo Mix 12 US$ 7,00 US$ 84,00
OR Save-a-lot Markets 10935 Chai 21 US$ 18,00 US$ 378,00
OR Save-a-lot Markets 10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
OR Save-a-lot Markets 10935 Tunnbröd 8 US$ 9,00 US$ 72,00
OR Gourmet Lanchonetes 10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
OR Split Rail Beer & Ale 10961 Filo Mix 6 US$ 7,00 US$ 42,00
OR Split Rail Beer & Ale 10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
OR Lazy K Kountry Store 10969 Spegesild 9 US$ 12,00 US$ 108,00
NM Old World Delicatessen 10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
NM White Clover Markets 10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
NM White Clover Markets 10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
NM White Clover Markets 10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60

To create a summary for the ItemTotal column we need only the promised 2 lines of code:

protected void Page_Load(object sender, EventArgs e) {     GridViewHelper helper = new GridViewHelper(this.GridView1);     helper.RegisterSummary(“ItemTotal”, SummaryOperation.Sum); }

First we create the GridViewHelper setting the grid in which it will act in the constructor. Then we register the summary specifying the column name and the summary operation to be performed. The result is below:

ShipRegion ShipName OrderId ProductName Quantity UnitPrice ItemTotal
NM Old World Delicatessen 10922 Alice Mutton 15 US$ 39,00 US$ 585,00
NM Old World Delicatessen 10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
NM Old World Delicatessen 10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
NM Old World Delicatessen 10925 Filo Mix 12 US$ 7,00 US$ 84,00
OR Save-a-lot Markets 10935 Chai 21 US$ 18,00 US$ 378,00
OR Save-a-lot Markets 10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
OR Save-a-lot Markets 10935 Tunnbröd 8 US$ 9,00 US$ 72,00
OR Gourmet Lanchonetes 10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
OR Split Rail Beer & Ale 10961 Filo Mix 6 US$ 7,00 US$ 42,00
OR Split Rail Beer & Ale 10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
OR Lazy K Kountry Store 10969 Spegesild 9 US$ 12,00 US$ 108,00
NM Old World Delicatessen 10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
NM White Clover Markets 10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
NM White Clover Markets 10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
NM White Clover Markets 10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
US$ 20.550,10

In this sample a new line was added to display the summary. Another option is to use the footer row to display the summary instead of creating a new one. When a new row is added to the grid, only the required cells to display the summarized columns are created. Using the footer, all the cells are created. In case of group summaries, generation of all cells or only the needed cells is a group attribute.

Now we will create a group. The code is shown below:

protected void Page_Load(object sender, EventArgs e)
{
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     helper.RegisterGroup(“ShipRegion”, true, true);
     helper.ApplyGroupSort();
 }

The first parameter of RegisterGroup method defines the columns to which the group must be created. It’s also possible to create a composite group, consisting of an array of columns. The second parameter specifies if the group is automatic. In this case a new row will be created automatically for the group header. The third parameter specifies if the group columns must be hidden. The ApplyGroupSort method sets the sort expression of the grid as being the group columns, in this case, ShipRegion. This is required to grouping works properly, except if the data comes ordered from database.

In the above sample the column ShipRegion have been hidden:

ShipName OrderId ProductName Quantity UnitPrice ItemTotal
NM
Old World Delicatessen 10922 Alice Mutton 15 US$ 39,00 US$ 585,00
Old World Delicatessen 10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
Old World Delicatessen 10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
Old World Delicatessen 10925 Filo Mix 12 US$ 7,00 US$ 84,00
Old World Delicatessen 10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
White Clover Markets 10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
White Clover Markets 10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
White Clover Markets 10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
OR
Save-a-lot Markets 10935 Chai 21 US$ 18,00 US$ 378,00
Save-a-lot Markets 10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
Save-a-lot Markets 10935 Tunnbröd 8 US$ 9,00 US$ 72,00
Gourmet Lanchonetes 10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
Split Rail Beer & Ale 10961 Filo Mix 6 US$ 7,00 US$ 42,00
Split Rail Beer & Ale 10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
Lazy K Kountry Store 10969 Spegesild 9 US$ 12,00 US$ 108,00

Let’s make something more interesting, let’s add a summary to the created group. We need just one more line to register the summary to the group:

protected void Page_Load(object sender, EventArgs e)
{
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     helper.RegisterGroup(“ShipRegion”, true, true);
     helper.RegisterSummary(“ItemTotal”, SummaryOperation.Sum, “ShipRegion”);
     helper.ApplyGroupSort();
 }

This time, the RegisterSummary method takes another parameter. The parameter specifies the name of the group to which the summary must be created. Group name is automatically generated from the group column names. If the group has only one column, group name will be the name of that column. If the group has more than one column, the group name will be the ordered concatenation of the columns that composes the group, joined with a plus sign (“+”): “ShipRegion+ShipName”.

We can see below the grid with grouping and a summary for the group:

ShipName OrderId ProductName Quantity UnitPrice ItemTotal
NM
Old World Delicatessen 10922 Alice Mutton 15 US$ 39,00 US$ 585,00
Old World Delicatessen 10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
Old World Delicatessen 10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
Old World Delicatessen 10925 Filo Mix 12 US$ 7,00 US$ 84,00
Old World Delicatessen 10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
White Clover Markets 10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
White Clover Markets 10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
White Clover Markets 10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
US$ 18.465,10
OR
Save-a-lot Markets 10935 Chai 21 US$ 18,00 US$ 378,00
Save-a-lot Markets 10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
Save-a-lot Markets 10935 Tunnbröd 8 US$ 9,00 US$ 72,00
Gourmet Lanchonetes 10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
Split Rail Beer & Ale 10961 Filo Mix 6 US$ 7,00 US$ 42,00
Split Rail Beer & Ale 10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
Lazy K Kountry Store 10969 Spegesild 9 US$ 12,00 US$ 108,00
US$ 2.085,00

It’s possible to create more than one group in the grid, simulating a hierarchical grouping, as seen below:

protected void Page_Load(object sender, EventArgs e)
 {
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     helper.RegisterGroup(“ShipRegion”, true, true);
     helper.RegisterGroup(“ShipName”, true, true);
     helper.ApplyGroupSort();
 }

Result:

OrderId ProductName Quantity UnitPrice ItemTotal
NM
Old World Delicatessen
10922 Alice Mutton 15 US$ 39,00 US$ 585,00
10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
10925 Filo Mix 12 US$ 7,00 US$ 84,00
10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
White Clover Markets
10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
OR
Lazy K Kountry Store
10969 Spegesild 9 US$ 12,00 US$ 108,00
Gourmet Lanchonetes
10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
Split Rail Beer & Ale
10961 Filo Mix 6 US$ 7,00 US$ 42,00
10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
Save-a-lot Markets
10935 Chai 21 US$ 18,00 US$ 378,00
10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
10935 Tunnbröd 8 US$ 9,00 US$ 72,00

Visualization is compromised when there is more than one group. GridViewHelper has events to allow easy implementation of visual or functional adjusts. The list of events follows below:

GroupStart Occurs when a new group starts, it means, when new values are found in the group column.
GroupEnd Occurs in the last row of the group
GroupHeader Occurs when an automatic header row is added for the group. The event is not triggered if the group is not automatic.
GroupSummary Occurs when the summary row is generated for the group. The event is not triggered if the group is not automatic, but will be triggered if the group is a suppression group (will be seen later on).
GeneralSummary Occurs after the general summaries be calculated. If the summary is automatic the event occurs after the summary row be added and after the summary values be placed in the row.
FooterDataBound Occurs in the footer databinding.

With a few more lines of code we can improve the visual aspect of the grid:

protected void Page_Load(object sender, EventArgs e)
 {
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     helper.RegisterGroup(“ShipRegion”, true, true);
     helper.RegisterGroup(“ShipName”, true, true);
     helper.GroupHeader += new GroupEvent(helper_GroupHeader);
     helper.ApplyGroupSort();
}    
private void helper_GroupHeader(string groupName, object[] values, GridViewRow row)
 {
     if ( groupName == “ShipRegion” )
     {
         row.BackColor = Color.LightGray;
         row.Cells[0].Text = “  ” + row.Cells[0].Text;
     }
     else if (groupName == “ShipName”)
     {
         row.BackColor = Color.FromArgb(236, 236, 236);
         row.Cells[0].Text = “     ” + row.Cells[0].Text;
     }
 }

The grid after the cosmetics:

OrderId ProductName Quantity UnitPrice ItemTotal
  NM
     Old World Delicatessen
10922 Alice Mutton 15 US$ 39,00 US$ 585,00
10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
10925 Filo Mix 12 US$ 7,00 US$ 84,00
10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
     White Clover Markets
10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
  OR
     Lazy K Kountry Store
10969 Spegesild 9 US$ 12,00 US$ 108,00
     Gourmet Lanchonetes
10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
     Split Rail Beer & Ale
10961 Filo Mix 6 US$ 7,00 US$ 42,00
10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
     Save-a-lot Markets
10935 Chai 21 US$ 18,00 US$ 378,00
10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
10935 Tunnbröd 8 US$ 9,00 US$ 72,00

More grouping options

There are two more interesting samples. The first presents a composite group. The second defines a suppress group, that has the same behavior of the sql GROUP BY clause. The repeating values are suppressed, and a summary operation is performed on the other columns.

Below we can see the code and the grid appearance for the composite group:

protected void Page_Load(object sender, EventArgs e)
 {
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     string[] cols = new string[2];
     cols[0] = “ShipRegion”
    cols[1] = “ShipName”
    helper.RegisterGroup(cols, true, true);
     helper.ApplyGroupSort();
 }
OrderId ProductName Quantity UnitPrice ItemTotal
NM – Old World Delicatessen
10922 Alice Mutton 15 US$ 39,00 US$ 585,00
10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
10925 Filo Mix 12 US$ 7,00 US$ 84,00
10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
NM – White Clover Markets
10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
OR – Lazy K Kountry Store
10969 Spegesild 9 US$ 12,00 US$ 108,00
OR – Gourmet Lanchonetes
10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
OR – Split Rail Beer & Ale
10961 Filo Mix 6 US$ 7,00 US$ 42,00
10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
OR – Save-a-lot Markets
10935 Chai 21 US$ 18,00 US$ 378,00
10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
10935 Tunnbröd 8 US$ 9,00 US$ 72,00

We can add a summary to the group. This time we will define an average operation and add a label to indicate the operation:

protected void Page_Load(object sender, EventArgs e)
{
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     string[] cols = new string[2];
     cols[0] = “ShipRegion”;     cols[1] = “ShipName”;
     helper.RegisterGroup(cols, true, true)
     helper.RegisterSummary(“ItemTotal”, SummaryOperation.Avg, “ShipRegion+ShipName”);
     helper.GroupSummary += new GroupEvent(helper_GroupSummary);     helper.ApplyGroupSort();
 }
private void helper_GroupSummary(string groupName, object[] values, GridViewRow row)
 {
     row.Cells[0].HorizontalAlign = HorizontalAlign.Right;
     row.Cells[0].Text = “Average”;
 }
OrderId ProductName Quantity UnitPrice ItemTotal
NM – Old World Delicatessen
10922 Alice Mutton 15 US$ 39,00 US$ 585,00
10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
10925 Filo Mix 12 US$ 7,00 US$ 84,00
10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
Average US$ 3.422,30
NM – White Clover Markets
10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
Average US$ 451,20
OR – Lazy K Kountry Store
10969 Spegesild 9 US$ 12,00 US$ 108,00
Average US$ 108,00
OR – Gourmet Lanchonetes
10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
Average US$ 155,00
OR – Split Rail Beer & Ale
10961 Filo Mix 6 US$ 7,00 US$ 42,00
10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
Average US$ 561,00
OR – Save-a-lot Markets
10935 Chai 21 US$ 18,00 US$ 378,00
10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
10935 Tunnbröd 8 US$ 9,00 US$ 72,00
Average US$ 233,33

The last sample will create a suppress group. It’s important to mention that if a suppress group is defined, no other group may be created. In the same way, if there is already a group defined, we can’t create a suppress group and an exception will be raised if we try it.

Below we can see the code and the grid appearance for the suppress group:

protected void Page_Load(object sender, EventArgs e)
{
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     helper.SetSuppressGroup(“ShipName”);
     helper.RegisterSummary(“Quantity”, SummaryOperation.Sum, “ShipName”);
     helper.RegisterSummary(“ItemTotal”, SummaryOperation.Sum, “ShipName”);
     helper.ApplyGroupSort();
 }
ShipRegion ShipName OrderId ProductName Quantity UnitPrice ItemTotal
Lazy K Kountry Store 9 US$ 108,00
Gourmet Lanchonetes 20 US$ 155,00
Old World Delicatessen 147 US$ 17.111,50
White Clover Markets 59 US$ 1.353,60
Split Rail Beer & Ale 66 US$ 1.122,00
Save-a-lot Markets 33 US$ 700,00

No value is displayed for the columns that don’t have a summary operation defined. This makes sense because GridViewHelper doesn’t know how to proceed to summarize the values found in the group rows to a unique value. This reminds the certain known message:

“Column ‘column_name’ is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.”

It doesn’t make sense to display the columns that don’t have a summary operation, and to hide them we need to call a method:

protected void Page_Load(object sender, EventArgs e)
{
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     helper.SetSuppressGroup(rdBtnLstGroup.SelectedValue)
     helper.RegisterSummary(“Quantity”, SummaryOperation.Sum, “ShipName”);
     helper.RegisterSummary(“ItemTotal”, SummaryOperation.Sum, “ShipName”);
     helper.SetInvisibleColumnsWithoutGroupSummary();     helper.ApplyGroupSort();
 }

I know, it’s a big big name! The resulting grid can be seen below:

ShipName Quantity ItemTotal
Lazy K Kountry Store 9 US$ 108,00
Gourmet Lanchonetes 20 US$ 155,00
Old World Delicatessen 147 US$ 17.111,50
White Clover Markets 59 US$ 1.353,60
Split Rail Beer & Ale 66 US$ 1.122,00
Save-a-lot Markets 33 US$ 700,00

Summary operations

GridViewHelper has 3 built-in summary operations: sum, average and row count. A very useful feature is the possibility of define custom summary operations. To achieve this we need to provide two methods to the GridViewHelper. A method will be called for each row found in the grid (or group) and the other will be called to retrieve the result of the summary operation. Below we have a sample of a custom summary operation. The semi-dummy operation will return the minimum value found:

private List<int> mQuantities = new List<int>();
protected void
Page_Load(object sender, EventArgs e)
   {
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     helper.RegisterSummary(“Quantity”, SaveQuantity, GetMinQuantity);
 }
private void SaveQuantity(string column, string group, object value)
 {
     mQuantities.Add(Convert.ToInt32(value));
 }
private object GetMinQuantity(string column, string group)
 {
     int[] qArray = new int[mQuantities.Count];
     mQuantities.CopyTo(qArray);
     Array.Sort(qArray);
     return qArray[0];
 }

In the code above we can see the required methods signatures. Both receive the summarized group and column names. If the summary is not relative to a group, the group parameter will be null. The method that is called for each row found in the grid, receives also the value of the column in the current row.

The resulting grid can be seen below :

ShipRegion ShipName OrderId ProductName Quantity UnitPrice ItemTotal
NM Old World Delicatessen 10922 Alice Mutton 15 US$ 39,00 US$ 585,00
NM Old World Delicatessen 10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
NM Old World Delicatessen 10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
NM Old World Delicatessen 10925 Filo Mix 12 US$ 7,00 US$ 84,00
OR Save-a-lot Markets 10935 Chai 21 US$ 18,00 US$ 378,00
OR Save-a-lot Markets 10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
OR Save-a-lot Markets 10935 Tunnbröd 8 US$ 9,00 US$ 72,00
OR Gourmet Lanchonetes 10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
OR Split Rail Beer & Ale 10961 Filo Mix 6 US$ 7,00 US$ 42,00
OR Split Rail Beer & Ale 10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
OR Lazy K Kountry Store 10969 Spegesild 9 US$ 12,00 US$ 108,00
NM Old World Delicatessen 10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
NM White Clover Markets 10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
NM White Clover Markets 10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
NM White Clover Markets 10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
4

Limitations

In one sample we said that we can simulate a hierarchical grouping. Although the grid appears to present a hierarchical grouping, the actual implementation isn’t hierarchical. There’s no group or subgroup. There are only sequentially registered groups. This becomes a problem if we need to create a summary for an inner group. Below we can see what happens in this situation:

protected void Page_Load(object sender, EventArgs e)
{
     GridViewHelper helper = new GridViewHelper(this.GridView1);
     helper.RegisterGroup(“ShipRegion”, true, true)
    helper.RegisterGroup(“ShipName”, true, true);
     helper.RegisterSummary(“ItemTotal”, SummaryOperation.Sum, “ShipName”);
     helper.RegisterSummary(“ItemTotal”, SummaryOperation.Sum);
     helper.GroupSummary += new GroupEvent(helper_Bug);
     helper.ApplyGroupSort();
 }
private void helper_Bug(string groupName, object[] values, GridViewRow row)
 {
     if (groupName == null) return;
row.BackColor = Color.Bisque;
     row.Cells[0].HorizontalAlign = HorizontalAlign.Center;
     row.Cells[0].Text = “[ Summary for ” + groupName + ” ” + values[0] + ” ]”;
 }
OrderId ProductName Quantity UnitPrice ItemTotal
NM
Old World Delicatessen
10922 Alice Mutton 15 US$ 39,00 US$ 585,00
10922 Teatime Chocolate Biscuits 35 US$ 4,50 US$ 157,50
10925 Inlagd Sill 25 US$ 19,00 US$ 475,00
10925 Filo Mix 12 US$ 7,00 US$ 84,00
10981 Côte de Blaye 60 US$ 263,50 US$ 15.810,00
[ Summary for ShipName Old World Delicatessen ] US$ 17.111,50
White Clover Markets
10989 Grandma’s Boysenberry Spread 40 US$ 25,00 US$ 1.000,00
10989 Queso Cabrales 15 US$ 21,00 US$ 315,00
10989 Camembert Pierrot 4 US$ 9,65 US$ 38,60
OR
[ Summary for ShipName White Clover Markets ] US$ 1.353,60
Lazy K Kountry Store
10969 Spegesild 9 US$ 12,00 US$ 108,00
[ Summary for ShipName Lazy K Kountry Store ] US$ 108,00
Gourmet Lanchonetes
10959 Rhönbräu Klosterbier 20 US$ 7,75 US$ 155,00
[ Summary for ShipName Gourmet Lanchonetes ] US$ 155,00
Split Rail Beer & Ale
10961 Filo Mix 6 US$ 7,00 US$ 42,00
10961 Lakkalikööri 60 US$ 18,00 US$ 1.080,00
[ Summary for ShipName Split Rail Beer & Ale ] US$ 1.122,00
Save-a-lot Markets
10935 Chai 21 US$ 18,00 US$ 378,00
10935 Carnarvon Tigers 4 US$ 62,50 US$ 250,00
10935 Tunnbröd 8 US$ 9,00 US$ 72,00
[ Summary for ShipName Save-a-lot Markets ] US$ 700,00
US$ 20.550,10

As we can see, the summary is created after the header of the outer group. This occurs because the event sequence is:

Group1_Start         Group1_End         Group2_Start         Group2_End

To a hierarchical grouping, the event sequence should be:

Group1_Start         Group2_Start         Group2_End         Group1_End

Implementation

GridViewHelper was implemented as a standalone class instead of an inherited class. This makes possible to use the GridViewHelper with any GridView, and doesn’t force the developer to inherit a specific GridView, what could affect the classes design. There’s another four classes in the solution:  GridViewSummary, GridViewGroup, GridViewSummaryList and GridViewGroupList. The “list” classes were created to allow access by a string indexer: helper.GeneralSummaries[“ItemTotal”].Value.

When the GridViewHelper is created, a reference to the target GridView is saved, and the RowDataBound event is bound to the method that does the hard work:

public GridViewHelper(GridView grd, bool useFooterForGeneralSummaries, SortDirection groupSortDirection)
 {
     this.mGrid = grd;
     this.useFooter = useFooterForGeneralSummaries;
     this.groupSortDir = groupSortDirection;
     this.mGeneralSummaries = new GridViewSummaryList();
     this.mGroups = new GridViewGroupList();
     this.mGrid.RowDataBound += new GridViewRowEventHandler(RowDataBoundHandler);
 }

Some methods used internally by the GridViewHelper were defined public because they provide some useful features that may be needed for some customizations. There are a few other options that wasn’t shown in the samples but that can be easily verified with Visual Studio intellisense.

SharePoint Online Learning Materials for IT Professionals

Are you an IT Professional looking to learn more about how
SharePoint Online can help supplement your on-premise SharePoint 2010 Products
deployment?  We’ve recently put together a comprehensive set of
learning materials that illustrate the benefits of SharePoint Online and how you
can leverage its capabilities to bring additional value to your on-premise
deployment.

Video and Origional Post Link

http://sharepoint.microsoft.com/blog/Pages/BlogPost.aspx?pID=990

 

Chart Control Asp.net 4.0 and IIS 7 Problem

I’ve decided to add the new ASP.NET 4.0 Chart Control to one of my web apps. Everything worked fine during the testing on my local machine, but once I published it to remote IIS 7.0 server I’ve got the following error:

HTTP Error 500.23 – Internal Server Error
An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode.

So the simple solution that worked for me was just to remove the following entry from web.config <system.web> section:

<httpHandlers>
<add path="ChartImg.axd" verb="GET,HEAD,POST" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler,
System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"
validate="false"/>
</httpHandlers>

Also make sure that <system.webServer> section has the following:

<handlers>
<remove name="ChartImageHandler" />
<add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD,POST"
path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler,
System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</handlers>

Hello Friends..

Victor Suggest me some cool stuff change just add below highlight line and it work in both IIS and debug mode…. Nice and rocking…..

<system.webServer>
   <validation validateIntegratedModeConfiguration=”false”/>
    <handlers>
      <remove name=”ChartImageHandler” />
      <add name=”ChartImageHandler” preCondition=”integratedMode” verb=”GET,HEAD,POST”
          path=”ChartImg.axd” type=”System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />
    </handlers>
  </system.webServer>
  <system.web>
    <httpHandlers>
      <add path=”ChartImg.axd”
           verb=”GET,HEAD,POST”
          type=”System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″
           validate=”false” />
    </httpHandlers>
</system.web>

 

Visual Studio 2010 Shortcut Keys

Hi,

Get file which contains many useful shortcut for Visual Studio 2010.

301 permanent redirects and ASP.Net 4.0

Hello all,

In this post, I would like to talk about a new method of the Response object that comes with ASP.Net 4.0.

The name of the method is RedirectPermanent.

Let’s talk a bit about 301 redirection and permanent redirection.301 redirect is the most efficient and Search Engine Friendly method for webpage redirection.

Let’s imagine that we have this scenario. This is a very common scenario. We have redesigned and move folders to some pages that have high search engine rankings. We do not want to lose those rankings.

We can permanently redirect traffic to the new pages without losing page rankings by using the 301 permanent redirect. RedirectPermanent help us to achieve that.

In order to demonstrate this new helper method, I will create the default asp.net website that comes with asp.net 4.0.

1) Fire VS 2010 and create a new website. Choose the filesystem to save your website ann VB as the .net language for this website

This is a much richer template that the previous ones that were created with VS 2008.

We have a Home page and an About page.

2) Create a new page and call it NewAbout (NewAbout.aspx)

3) Write some dummy content on it like “This is our new About us page”

4) Move to the About.aspx.vb, and in the page load event, type the following

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Response.RedirectPermanent(“~/NewAbout.aspx”)
End Sub

5)  Now run your application and then click “About” page. You will permanently redirect to the new “NewAbout” page.

Hope it helps!!!!

%d bloggers like this: