FlexGrid
Custom Footers
This sample shows how to extend FlexGrid to provide two types of footer elements.
Features
ID
Start
End
Country
Product
Color
Amount2
Discount
Active
1
1/25/2025
1/25/2025
Japan
Gadget
Green
$4,973.59
8%
2
2/25/2025
2/25/2025
France
Gadget
Black
$1,595.47
23%
$1,274,023.75
12%
ID
Start
End
Country
Product
Color
Amount2
Discount
Active
Σ
0
Description
This sample shows how to extend FlexGrid to provide two types of footer elements.
- Column Footer Rows: In some situations you may want to display non-scrollable rows below the grid data containing summary information such as subtotals. This can be done by the ShowColumnFooters(bool value = true, string rowHeaderText = null) method. The grid will automatically provide values for any columns that have the Aggregate property set. This is what this sample does.
- Group Footer Rows: When grouping is enabled, FlexGrid adds group rows above each group. This sample shows how you can add custom group rows below each group as well.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using System.Web.Mvc; using System.Collections.Generic; using C1.Web.Mvc.Grid; using MvcExplorer.Models; namespace MvcExplorer.Controllers { public partial class FlexGridController : Controller { public ActionResult CustomFooters() { return View(Sale.GetData(500)); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | @model IEnumerable< Sale > @using C1.Web.Mvc.Grid; @section Scripts{ <script> // class used to identify group footer rows var ROW_FOOTER_CLASS = 'wj-groupfooter' ; function grouping(groupBy) { var flex = wijmo.Control.getControl( '#grid' ), data = flex.collectionView; flex.beginUpdate(); data.groupDescriptions.clear(); var groups = groupBy ? groupBy.split( ',' ) : []; for ( var i = 0; i < groups.length ; i++) { data.groupDescriptions.push( new wijmo.collections.PropertyGroupDescription(groups[i])); } flex.endUpdate(); } function onLoadedRows() { var flex = wijmo .Control.getControl( '#grid' ); if (flex.collectionView.groupDescriptions.length) { addGroupFooters(); } } // add group footers function addGroupFooters() { var flex = wijmo .Control.getControl( '#grid' ); flex.beginUpdate(); for ( var r = 0 ; r < flex.rows.length; r++) { var row = flex .rows[r]; if (row instanceof wijmo.grid.GroupRow && row.cssClass != ROW_FOOTER_CLASS) { // create footer row to match this group row var newRow = new wijmo.grid.GroupRow(); newRow.level = row .level; newRow.cssClass = ROW_FOOTER_CLASS ; // add footer row to the grid var index = findFooterIndex (r); flex.rows.insert(index, newRow); // add some content to footer row var group = row .dataItem; flex.setCellData(index, 0, 'f(' + group.name + ')' , false ); } } flex.endUpdate(); } // find the index where the group footer should be inserted function findFooterIndex(r) { var flex = wijmo .Control.getControl( '#grid' ); var level = flex .rows[r].level; for ( var i = r + 1; i < flex.rows.length; i++) { var row = flex .rows[i]; if (row instanceof wijmo.grid.GroupRow) { // if this is *not* a footer and the level is <=, insert here if (row.cssClass != ROW_FOOTER_CLASS && row.level <= level) { return i; } // if this *is* a footer and the level is <, insert here if (row.cssClass == ROW_FOOTER_CLASS && row.level < level) { return i; } } } // insert at the bottom return flex.rows.length; } </script> } < style > .wj-control .wj-btn-group { border: 1px solid rgba(0, 0, 0, 0.2); } .wj-control .wj-btn-group * { color: black !important; } .wj-control .wj-btn-group > *:not(:first-child) { border-left: 1px solid rgba(0, 0, 0, 0.2); } .wj-control .wj-btn-group > .wj-btn.wj-btn- default :hover, .wj-control .wj-btn-group > .wj-btn.wj-btn- default :focus { background: #eee !important; } </ style > < label > @Html .Raw(Resources.FlexGrid.CustomFooters_Text1)</ label > < div class = "wj-btn-group" > < button type = "button" class = "wj-btn wj-btn-default" onclick = "grouping('')" > @Html .Raw(Resources.FlexGrid.CustomFooters_None)</ button > < button type = "button" class = "wj-btn wj-btn-default" onclick = "grouping('Country')" > @Html .Raw(Resources.FlexGrid.CustomFooters_Country)</ button > < button type = "button" class = "wj-btn wj-btn-default" onclick = "grouping('Product')" > @Html .Raw(Resources.FlexGrid.CustomFooters_Product)</ button > < button type = "button" class = "wj-btn wj-btn-default" onclick = "grouping('Product,Color')" > @Html .Raw(Resources.FlexGrid.CustomFooters_ProductAndColor)</ button > </ div > < label > @Html .Raw(Resources.FlexGrid.CustomFooters_Text2)</ label > < div class = "multi-grid" > @ (Html.C1().FlexGrid< Sale >().Id( "grid" ).IsReadOnly( true ) .AutoGenerateColumns( false ) .ShowGroups( true ) .Bind(b => b.Bind(Model).DisableServerRead( true )) // disable server read to use grouping .CssClass( "grid" ) .OnClientLoadedRows( "onLoadedRows" ) .Columns(columns => { columns.Add(column => column.Binding( "ID" ).Width( "70" )); columns.Add(column => column.Binding( "Start" )); columns.Add(column => column.Binding( "End" )); columns.Add(column => column.Binding( "Country" )); columns.Add(column => column.Binding( "Product" )); columns.Add(column => column.Binding( "Color" )); columns.Add(column => column.Binding( "Amount2" ).Format( "c" ).Aggregate(Aggregate.Sum)); columns.Add(column => column.Binding( "Discount" ).Width( "100" ).Format( "p0" ).Aggregate(Aggregate.Avg)); columns.Add(column => column.Binding( "Active" ).Width( "80" )); }).ShowColumnFooters() ) </ div > @section Summary{ @Html .Raw(Resources.FlexGrid.CustomFooters_Text0) } @section Description{ < p > @Html .Raw(Resources.FlexGrid.CustomFooters_Text0)</ p > < ol > < li > @Html .Raw(Resources.FlexGrid.CustomFooters_Li1)</ li > < li > @Html .Raw(Resources.FlexGrid.CustomFooters_Li2)</ li > </ ol > } |