Summaries
Actual applications often require displaying aggregated information that contains various totals, average and maximum data values for various hierarchical levels of the grid. This information should always be displayed in fixed rows above or below content and should not be involved in sorting.

Docked rows are the most convenient and efficient way of displaying this kind of information. A programmer may add business objects performing data aggregation or just add an empty row and display information in PaintCell or PaintRow events.
grid.PaintRow += delegate(object sender, PaintRowEventArgs e) { if (Equals(RowDockStyle.Bottom, e.Row.Dock)) { //Do default painting routines e.Appearance.BackColor = Color.FromArgb(226, 237, 252); e.Appearance.GradientEndBackColor = Color.FromArgb(198, 218, 249); e.Appearance.GradientEnabled = true; e.Appearance.GradientDirection = GradientDirection.Vertical; e.PaintAll(); e.Handled = true; string s = string.Format("Sum1 = {0}, Sum2 = {1}, Sum3 = {2}", GetSummary(e.Row.Parent, grid.Headers[1]["Id1"]), GetSummary(e.Row.Parent, grid.Headers[1]["Id2"]), GetSummary(e.Row.Parent, grid.Headers[1]["Id3"])); e.Graphics.DrawString(s, _summaryFont, Brushes.Black, e.Bounds); } else if (Equals(RowDockStyle.Top, e.Row.Dock)) { e.Appearance.BackColor = Color.FromArgb(254, 243, 224); e.Appearance.GradientEndBackColor = Color.FromArgb(252, 227, 182); e.Appearance.GradientEnabled = true; e.Appearance.GradientDirection = GradientDirection.Vertical; } }; grid.PaintCell += delegate(object sender, PaintCellEventArgs e) { if (e.Cell.Column != null && Equals(RowDockStyle.Top, e.Cell.Row.Dock)) { e.Text = string.Format("{0}", GetSummary(e.Cell.Row.Parent, e.Cell.Column)); e.Font = _summaryFont; } } static int GetSummary(Row parentRow, Column column) { int sum = 0; foreach (Row child in parentRow.Children) { //Don't count sum rows. if (Equals(RowDockStyle.None, child.Dock)) { sum += (int)child[column.Id].Value; } } return sum; }