Wednesday, 14 December 2011

Custom Grid control with grouping


Introduction
This article explains and illustrates how the standard functionality provided by the Web Controls can be extended in order to fit the requirements of an individual or enterprise.

Background
I was working on a project that deals with the Gridview, with multiple ‘Grid Header’ with ‘Sub Header’. I have done this by using Table and a Panel. It could be done with a user control as well, but we thought it might be useful to come up with a Web Control instead, so that this can be used in other projects as well.

Using the code

Download the source code. Make The a solution with the source code for both the control as well as the sample aspx page that includes the control. The code is given below:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

[assembly: TagPrefix("Fv.Web.UI""FvGrid")]
namespace Fv.Web.UI
{
    [ParseChildren(true), PersistChildren(false)]
    [ToolboxData("<{0}:FvGrid runat=server></{0}:FvGrid>")]
    public sealed class FvGrid : WebControl, IStateManager
    {
        #region Private Variables
        private StateBag _viewstate;
        #endregion

        #region RenderControl
        public override void RenderControl(HtmlTextWriter writer)
        {
            refContainer.RenderControl(writer);
            base.RenderControl(writer);
        }
        #endregion

        #region Variables
        Table tbl;
        Panel refContainer;
        Panel refFilter;
        TextBox refFilterBox;
        private int __TotalRowCount;
        Dictionary<Int32List<FvGridColumn>> _dir;
        FvGridColumns _Cols;
        #endregion

        #region Events
        /// <summary>
        /// GridRowBinding event
        /// </summary>
        public event FvGridRowBinding GridRowBinding;
        /// <summary>
        /// GridCellBinding event
        /// </summary>
        public event FvGridCellBinding GridCellBinding;

        #endregion

        #region Grid
        public FvGrid()
        {
            refContainer = new Panel();
            _viewstate = new StateBag();
            _dir = new Dictionary<Int32List<FvGridColumn>>();
            _Cols = new FvGridColumns();
           
            _viewstate.Add("_Columns", _Columns);
            _viewstate.Add("_Groups", _Groups);
            _Columns = new FvGridColumns();
            _Groups = new FvGridGroups();
            this.FreezHeader = false;
            this.__TotalRowCount = 0;
            this.PadddingLeft = 10;

            _viewstate.Add("FreezHeader", FreezHeader);
            _viewstate.Add("ShowGroupColumn", ShowGroupColumn);
            _viewstate.Add("Width", Width);
            _viewstate.Add("Height", Height);
            _viewstate.Add("OnClientRowClick", OnClientRowClick);
            _viewstate.Add("OnClientRowDblClick", OnClientRowDblClick);
            _viewstate.Add("DataSource", DataSource);
            _viewstate.Add("CommandArgs", CommandArgs);
           
            _viewstate.Add("ColumnLable", ColumnLable);

            _viewstate.Add("CssClass", CssClass);
            _viewstate.Add("HeaderCssClass", HeaderCssClass);
            _viewstate.Add("RowCssClass", RowCssClass);
            _viewstate.Add("AlternateRowCssClass", AlternateRowCssClass);
            _viewstate.Add("FooterCssClass", FooterCssClass);
        }
        #endregion

        #region Properties
        #region CssClass
        /// <summary>
        /// Gets or sets the Cascading Style Sheet (CSS) class rendered by the Web server
        /// control on the client.
        /// </summary>
        public override String CssClass
        {
            get
            {
                return (String)_viewstate["CssClass"];
            }
            set
            {
                _viewstate["CssClass"] = value;
                _viewstate.SetItemDirty("CssClass"true);
            }
        }
      
        /// <summary>
        /// Gets or sets the Cascading Style Sheet (CSS) class rendered by the Web server
        /// control on the client for header row.
        /// </summary>
        public String HeaderCssClass
        {
            get
            {
                return (String)_viewstate["HeaderCssClass"];
            }
            set
            {
                _viewstate["HeaderCssClass"] = value;
                _viewstate.SetItemDirty("HeaderCssClass"true);
            }
        }
       
        /// <summary>
        /// Gets or sets the Cascading Style Sheet (CSS) class rendered by the Web server
        /// control on the client for row.
        /// </summary>
        public String RowCssClass
        {
            get
            {
                return (String)_viewstate["RowCssClass"];
            }
            set
            {
                _viewstate["RowCssClass"] = value;
                _viewstate.SetItemDirty("RowCssClass"true);
            }
        }
       
        /// <summary>
        /// Gets or sets the Cascading Style Sheet (CSS) class rendered by the Web server
        /// control on the client for alternate row.
        /// </summary>
        public String AlternateRowCssClass
        {
            get
            {
                return (String)_viewstate["AlternateRowCssClass"];
            }
            set
            {
                _viewstate["AlternateRowCssClass"] = value;
                _viewstate.SetItemDirty("AlternateRowCssClass"true);
            }
        }
       
        /// <summary>
        /// Gets or sets the Cascading Style Sheet (CSS) class rendered by the Web server
        /// control on the client for footer row.
        /// </summary>
        public String FooterCssClass
        {
            get
            {
                return (String)_viewstate["FooterCssClass"];
            }
            set
            {
                _viewstate["FooterCssClass"] = value;
                _viewstate.SetItemDirty("FooterCssClass"true);
            }
        }
        #endregion

        public Boolean FreezHeader
        {
            get
            {
                return _viewstate["FreezHeader"] == null ? false : (Boolean)_viewstate["FreezHeader"];
            }
            set
            {
                _viewstate["FreezHeader"] = value;
                _viewstate.SetItemDirty("FreezHeader"true);
            }
        }
       
        /// <summary>
        /// Get or set the GroupColumn columns are show or not,Defauls is false.
        /// </summary>
        public Boolean ShowGroupColumn
        {
            get
            {
                return _viewstate["ShowGroupColumn"] == null ? false : (Boolean)_viewstate["ShowGroupColumn"];
            }
            set
            {
                _viewstate["ShowGroupColumn"] = value;
                _viewstate.SetItemDirty("ShowGroupColumn"true);
            }
        }

        /// <summary>
        /// Gets or sets the width of the Web server control.
        /// </summary>
        public override Unit Width
        {
            get
            {
                return _viewstate["Width"] == null ? Unit.Pixel(100) : (Unit)_viewstate["Width"];
            }
            set
            {
                _viewstate["Width"] = value;
                _viewstate.SetItemDirty("Width"true);
            }
        }
       
        /// <summary>
        /// Gets or sets the height of the Web server control.
        /// </summary>
        public override Unit Height
        {
            get
            {
                return _viewstate["Height"] == null ? Unit.Pixel(10) : (Unit)_viewstate["Height"];
            }
            set
            {
                _viewstate["Height"] = value;
                _viewstate.SetItemDirty("Height"true);
            }
        }
       
        /// <summary>
        /// Gets or sets the OnClientRowClick event is rise when Row Click on the client.
        /// </summary>
        public String OnClientRowClick
        {
            get
            {
                return (String)_viewstate["OnClientRowClick"];
            }
            set
            {
                _viewstate["OnClientRowClick"] = value;
                _viewstate.SetItemDirty("OnClientRowClick"true);
            }
        }
       
        /// <summary>
        /// Gets or sets the OnClientRowDblClick event is rise when Row Dbl Click on the client.
        /// </summary>
        public String OnClientRowDblClick
        {
            get
            {
                return (String)_viewstate["OnClientRowDblClick"];
            }
            set
            {
                _viewstate["OnClientRowDblClick"] = value;
                _viewstate.SetItemDirty("OnClientRowDblClick"true);
            }
        }

        /// <summary>
        /// Gets a collection of Fv.Web.UI.FvGridColumns objects that
        /// represent the column fields in a Fv.Web.UI.FvGrid control.
        /// </summary>
        [PersistenceMode(PersistenceMode.InnerProperty),]
        public FvGridColumns Columns
        {
            get
            {
                if (_Columns == null)
                {
                    _Columns = new FvGridColumns();
                    if (base.IsTrackingViewState)
                    {
                        _Columns.TrackViewState();
                    }
                }
                return _Columns;
            }
            set
            {
                _Columns = value;
            }
        }
       
        /// <summary>
        /// Gets a collection of Fv.Web.UI.FvGridGroups objects that
        /// represent the column fields in a Fv.Web.UI.FvGrid control.
        /// </summary>
        [PersistenceMode(PersistenceMode.InnerProperty),]
        public FvGridGroups Groups
        {
            get
            {
                if (_Groups == null)
                {
                    _Groups = new FvGridGroups();
                    if (base.IsTrackingViewState)
                    {
                        _Groups.TrackViewState();
                    }
                }
                return _Groups;
            }
            set
            {
                _Groups = value;
            }
        }
       
        /// <summary>
        /// Gets or sets the DataTable from which the data-bound control retrieves its list
        /// of data items.
        /// </summary>
        public DataTable DataSource
        {
            get
            {
                return (DataTable)_viewstate["DataSource"];
            }
            set
            {
                _viewstate["DataSource"] = value;
                _viewstate.SetItemDirty("DataSource"true);
            }
        }
       
        /// <summary>
        /// Gets or sets an optional argument that provides additional information about
        /// the property.
        /// </summary>
        public String CommandArgs
        {
            get
            {
                return (String)_viewstate["CommandArgs"];
            }
            set
            {
                _viewstate["CommandArgs"] = value;
                _viewstate.SetItemDirty("CommandArgs"true);
            }
        }
        public Int32 PadddingLeft
        {
            get;
            set;
        }
        private FvGridColumns _Columns
        {
            get
            {
                return (FvGridColumns)_viewstate["_Columns"];
            }
            set
            {
                _viewstate["_Columns"] = value;
                _viewstate.SetItemDirty("_Columns"true);
            }
        }
        private FvGridGroups _Groups
        {
            get
            {
                return (FvGridGroups)_viewstate["_Groups"];
            }
            set
            {
                _viewstate["_Groups"] = value;
                _viewstate.SetItemDirty("_Groups"true);
            }
        }
        private Int32 ColumnLable
        {
            get
            {
                return _viewstate["ColumnLable"] == null ? 0 : (Int32)_viewstate["ColumnLable"];
            }
            set
            {
                _viewstate["ColumnLable"] = value;
                _viewstate.SetItemDirty("ColumnLable"true);
            }
        }
        private Boolean IsAcesnding
        {
            get;
            set;
        }
        #endregion

        #region DataBind()
        /// <summary>
        /// Binds the data source to the Grid control.
        /// This method cannot be inherited.
        /// </summary>
        public override void DataBind()
        {
            #region CalculateColumn
            tbl = new Table();
            DataTable dt = DataSource;
            CalculateColumn(Columns);
            #endregion

            #region Header Row
            int totWidth = 0;
            __InsertHeaderRow(__InsertHeaderRow());
            /*
            int totWidth = Columns.Sum(a => a.Width).Value;*/
            if (totWidth > 0)
                tbl.Attributes.CssStyle.Add(HtmlTextWriterStyle.Width, totWidth.ToString() + "px");
            #endregion

            #region No Data Found Row
            if (dt.Rows.Count == 0)
            {
                TableRow oRowNodatafound = new TableRow();
                if (RowCssClass != string.Empty)
                    oRowNodatafound.Attributes.Add("class", RowCssClass);
                tbl.Rows.Add(oRowNodatafound);

                TableCell oCellNodatafound = new TableCell();
                oCellNodatafound.HorizontalAlign = HorizontalAlign.Center;
                oCellNodatafound.Text = "No Data Found";
                oCellNodatafound.ColumnSpan = _Cols.Count;
                oRowNodatafound.Cells.Add(oCellNodatafound);
            }
            #endregion

            #region Data Row
            if (Groups.Count > 0)
            {
                string[] GroupsCols = new string[1] { Groups[0].DataField };
                __Grouping(GroupsCols, "");
            }
            else
            {
                for (int gRow = 0; gRow < dt.Rows.Count; gRow++)
                    __InsertRow(dt.Rows[gRow]);
            }
            #endregion

            #region tbl.Style
            tbl.Style.Add("text-overflow""ellipsis");
            tbl.Style.Add("border-collapse""collapse");
            tbl.Style.Add("empty-cells""show");

            #endregion

            #region refContainer
            refContainer.Controls.Clear();
            if (refContainer != null)
                refContainer.Controls.Add(tbl);
            #endregion
        }
        #endregion

        #region Private
        private List<FvGridColumn> CalculateColumn(FvGridColumns o)
        {
            ColumnLable++;
            List<FvGridColumn> _list = new List<FvGridColumn>();
            for (int i = 0; i < o.Count; i++)
            {
                _list.Add(o[i]);
                if (o[i].Columns.Count > 0)
                {
                    if (!_dir.ContainsKey(ColumnLable))
                        _dir.Add(ColumnLable, _list);
                    else
                        _dir[ColumnLable] = _list;
                    List<FvGridColumn> tt = CalculateColumn(o[i].Columns);
                    if (!_dir.ContainsKey(ColumnLable))
                        _dir.Add(ColumnLable, tt);
                    else
                        _dir[ColumnLable].AddRange(tt.AsEnumerable());
                    ColumnLable = 1;
                }
                else
                {
                    _Cols.Add(o[i]);
                }
            }
            return _list;
        }
        private void __Grouping(string[] GroupsCols, String Where)
        {
            DataRow[] Grdt = DataSource.DefaultView.ToTable(true, GroupsCols).Select(Where);
            for (int Irow = 0; Irow < Grdt.Length; Irow++)
            {
                //Insert Group Row
                __InsertRow(Grdt[Irow], true, GroupsCols[GroupsCols.Length - 1], GroupsCols.Length);
                string _wh = Convert.ToString(Where);

                for (int Icol = GroupsCols.Length - 1; Icol < GroupsCols.Length; Icol++)
                    _wh += " AND " + GroupsCols[Icol] + " ='" + Grdt[Irow][GroupsCols[Icol]] + "'";

                DataRow[] rows;
                if (GroupsCols.Length < Groups.Count)
                {
                    string[] _Cols = new string[(GroupsCols.Length + 1)];

                    for (int Icol = 0; Icol < (GroupsCols.Length + 1); Icol++)
                        _Cols[Icol] = Groups[Icol].DataField;

                    __Grouping(_Cols, _wh.Substring(4));
                }
                else
                {
                    _wh = _wh.Trim().StartsWith("AND") ? _wh.Substring(4) : _wh;
                    rows = DataSource.Select(_wh.Trim());

                    //Insert Data Row
                    for (int IDatarow = 0; IDatarow < rows.Length; IDatarow++)
                        __InsertRow(rows[IDatarow], GroupsCols.Length + 2);
                }
            }
        }
        private void __InsertRow(DataRow NewRow, Boolean IsGroupColumn, String GroupColumnName, Int32 Paddding)
        {
            this.__TotalRowCount++;
            TableRow oRow = new TableRow();
            if (OnClientRowClick != null)
                oRow.Attributes.Add("onclick", OnClientRowClick);
            if (OnClientRowDblClick != null)
                oRow.Attributes.Add("ondblclick", OnClientRowDblClick);

            if ((__TotalRowCount % 2) == 0 && RowCssClass != null)
                oRow.Attributes.Add("class", RowCssClass);
            else if (AlternateRowCssClass != null)
                oRow.Attributes.Add("class", AlternateRowCssClass);
            tbl.Rows.Add(oRow);

            TableCell oCell = new TableCell();
            oCell.HorizontalAlign = HorizontalAlign.Center;
            oCell.Text = IsGroupColumn ? NewRow[GroupColumnName].ToString() : NewRow[2].ToString();
            oCell.ColumnSpan = _Cols.Count - Groups.Count;
            oCell.Style.Add(HtmlTextWriterStyle.TextAlign, "left");
            oCell.Style.Add(HtmlTextWriterStyle.PaddingLeft, (Paddding * this.PadddingLeft).ToString() + "px");
            oRow.Cells.Add(oCell);

            if (GridCellBinding != null)
            {
                FvGridCellBindingArgs oCArgs = new FvGridCellBindingArgs();
                oCArgs.DataRow = NewRow;
                oCArgs.ItemCell = oCell;
                oCArgs.Column = new FvGridColumn();
                oCArgs.CommandArgs = this.CommandArgs;
                oCArgs.RowType = FvGridRowType.GroupRow;
                GridCellBinding(this, oCArgs);
            }
            if (GridRowBinding != null)
            {
                FvGridRowBindingArgs oArgs = new FvGridRowBindingArgs();
                oArgs.DataRow = NewRow;
                oArgs.ItemRow = oRow;
                oArgs.ItemRows = oRow.Cells;
                oArgs.CommandArgs = this.CommandArgs;
                oArgs.RowType = FvGridRowType.GroupRow;
                GridRowBinding(this, oArgs);
            }
        }
        private void __InsertRow(DataRow NewRow)
        {
            __InsertRow(NewRow, -1);
        }
        private void __InsertRow(DataRow NewRow, Int32 Paddding)
        {
            this.__TotalRowCount++;
            TableRow oRow = new TableRow();
            if (OnClientRowClick != null)
                oRow.Attributes.Add("onclick", OnClientRowClick);
            if (OnClientRowDblClick != null)
                oRow.Attributes.Add("ondblclick", OnClientRowDblClick);

            if ((__TotalRowCount % 2) == 0 && RowCssClass != null)
                oRow.Attributes.Add("class", RowCssClass);
            else if (AlternateRowCssClass != null)
                oRow.Attributes.Add("class", AlternateRowCssClass);

            tbl.Rows.Add(oRow);
            int FirstCellBing = 0;
            for (int gCol = 0; gCol < _Cols.Count; gCol++)
            {
                Boolean CanAddedCell = false;
                Boolean IsPresent = false;
                FvGridColumn oCol = _Cols[gCol];
                foreach (FvGridGroup grp in Groups)
                    if (grp.DataField == oCol.DataField)
                        IsPresent = true;

                if (ShowGroupColumn)
                    CanAddedCell = true;
                else if (!ShowGroupColumn && !IsPresent)
                    CanAddedCell = true;

                #region CanAddedCell
                if (CanAddedCell)
                {
                    FirstCellBing++;
                    TableCell oCell = new TableCell();
                    switch (oCol.Alignment)
                    {
                        case FvGridAlignment.Left:
                            oCell.HorizontalAlign = HorizontalAlign.Left;
                            break;
                        case FvGridAlignment.Center:
                            oCell.HorizontalAlign = HorizontalAlign.Center;
                            break;
                        case FvGridAlignment.Right:
                            oCell.HorizontalAlign = HorizontalAlign.Right;
                            break;
                    }
                    oCell.Text = oCol.DataFormat != null && oCol.DataFormat != string.Empty
                                ? String.Format(oCol.DataFormat, NewRow[oCol.DataField])
                                : Convert.ToString(NewRow[oCol.DataField]);
                    if (Groups.Count > 0 && FirstCellBing == 1)
                        oCell.Style.Add(HtmlTextWriterStyle.PaddingLeft, (Paddding * this.PadddingLeft).ToString() + "px");

                    if (oCell.Text == "")
                        oCell.Controls.Add(new LiteralControl("&nbsp;"));

                    if (FreezHeader && __TotalRowCount == 0)
                    {
                        if (oCol.Width != null)
                            oCell.Style.Add(HtmlTextWriterStyle.Width, Convert.ToString(oCol.Width) + "px");
                    }

                    if (GridCellBinding != null)
                    {
                        FvGridCellBindingArgs oCArgs = new FvGridCellBindingArgs();
                        oCArgs.DataRow = NewRow;
                        oCArgs.ItemCell = oCell;
                        oCArgs.Column = oCol;
                        oCArgs.CommandArgs = this.CommandArgs;
                        oCArgs.RowType = (__TotalRowCount % 2) == 0 ? FvGridRowType.Row : FvGridRowType.AlternateRow;
                        GridCellBinding(this, oCArgs);
                    }
                    oRow.Cells.Add(oCell);
                }
                #endregion
                if (GridRowBinding != null)
                {
                    FvGridRowBindingArgs oArgs = new FvGridRowBindingArgs();
                    oArgs.DataRow = NewRow;
                    oArgs.ItemRow = oRow;
                    oArgs.ItemRows = oRow.Cells;
                    oArgs.CommandArgs = this.CommandArgs;
                    oArgs.RowType = (__TotalRowCount % 2) == 0 ? FvGridRowType.Row : FvGridRowType.AlternateRow;
                    GridRowBinding(this, oArgs);
                }

            }
        }
        private bool __InsertHeaderRow()
        {
            bool IsMultiple = false;
            int totWidth = 0;
            for (int HCol = 0; HCol < _dir.Count; HCol++)
            {
                IsMultiple = true;
                TableHeaderRow oRowHeader = new TableHeaderRow();
                oRowHeader.TableSection = TableRowSection.TableHeader;
                oRowHeader.Style.Add("height""20px");
                if (CssClass != null && CssClass != string.Empty)
                    tbl.Attributes.Add("class", CssClass);

                tbl.Rows.Add(oRowHeader);

                for (int gCol = 0; gCol < _dir[HCol + 1].Count; gCol++)
                {
                    Boolean CanAddedCell = false;
                    Boolean IsPresent = false;
                    FvGridColumn oColHeader = _dir[HCol + 1][gCol];
                    foreach (FvGridGroup grp in Groups)
                        if (grp.DataField == oColHeader.DataField)
                            IsPresent = true;

                    if (ShowGroupColumn)
                        CanAddedCell = true;
                    else if (!ShowGroupColumn && !IsPresent)
                        CanAddedCell = true;

                    if (CanAddedCell)
                    {
                        TableHeaderCell oCell = new TableHeaderCell();
                        switch (oColHeader.Alignment)
                        {
                            case FvGridAlignment.Left:
                                oCell.HorizontalAlign = HorizontalAlign.Left;
                                break;
                            case FvGridAlignment.Center:
                                oCell.HorizontalAlign = HorizontalAlign.Center;
                                break;
                            case FvGridAlignment.Right:
                                oCell.HorizontalAlign = HorizontalAlign.Right;
                                break;
                        }
                        if (oColHeader.Columns.Count < 1)
                        {
                            totWidth += Convert.ToInt32(oColHeader.Width);
                        }
                        oCell.Text = oColHeader.ColumnName;
                        if (oColHeader.ColSpan > 0)
                        {
                            oCell.ColumnSpan = oColHeader.ColSpan;
                        }
                        if (oColHeader.RowSpan > 0)
                        {
                            oCell.RowSpan = oColHeader.RowSpan;
                        }

                        if (oColHeader.Width != null)
                            oCell.Style.Add(HtmlTextWriterStyle.Width, Convert.ToString(oColHeader.Width) + "px");

                        if (HCol == _dir.Count - 1)
                        {
                            if (oColHeader.Width != null)
                                oCell.Style.Add(HtmlTextWriterStyle.Width, Convert.ToString(oColHeader.Width) + "px");
                        }
                        if (HeaderCssClass != null)
                            oCell.Attributes.Add("class", HeaderCssClass);
                        oCell.Style.Add("white-space""nowrap");

                        if (GridCellBinding != null)
                        {
                            FvGridCellBindingArgs oCArgs = new FvGridCellBindingArgs();
                            oCArgs.DataRow = null;
                            oCArgs.ItemCell = oCell;
                            oCArgs.Column = oColHeader;
                            oCArgs.CommandArgs = this.CommandArgs;
                            oCArgs.RowType = FvGridRowType.Header;
                            GridCellBinding(this, oCArgs);
                        }
                        oRowHeader.Cells.Add(oCell);
                    }
                    if (GridRowBinding != null)
                    {
                        FvGridRowBindingArgs oArgs = new FvGridRowBindingArgs();
                        oArgs.DataRow = null;
                        oArgs.ItemRow = oRowHeader;
                        oArgs.CommandArgs = this.CommandArgs;
                        oArgs.ItemRows = oRowHeader.Cells;
                        oArgs.RowType = FvGridRowType.Header;
                        GridRowBinding(this, oArgs);
                    }
                }
            }
            return IsMultiple;
        }
        private void __InsertHeaderRow(bool IsMultiple)
        {
            int totWidth = 0;
            TableHeaderRow oRowHeader = new TableHeaderRow();
            oRowHeader.TableSection = TableRowSection.TableHeader;
            oRowHeader.Style.Add("height""20px");

            if (CssClass != null && CssClass != string.Empty)
                tbl.Attributes.Add("class", CssClass);

            totWidth = Columns.Sum(a => a.Width).Value;

            if (totWidth > 0)
                tbl.Attributes.CssStyle.Add(HtmlTextWriterStyle.Width, totWidth.ToString() + "px");

            tbl.Rows.Add(oRowHeader);

            for (int gCol = 0; gCol < Columns.Count; gCol++)
            {
                Boolean CanAddedCell = false;
                Boolean IsPresent = false;
                FvGridColumn oColHeader = Columns[gCol];
                foreach (FvGridGroup grp in Groups)
                    if (grp.DataField == oColHeader.DataField)
                        IsPresent = true;

                if (ShowGroupColumn)
                    CanAddedCell = true;
                else if (!ShowGroupColumn && !IsPresent)
                    CanAddedCell = true;

                if (CanAddedCell)
                {
                    TableHeaderCell oCell = new TableHeaderCell();
                    switch (oColHeader.Alignment)
                    {
                        case FvGridAlignment.Left:
                            oCell.HorizontalAlign = HorizontalAlign.Left;
                            break;
                        case FvGridAlignment.Center:
                            oCell.HorizontalAlign = HorizontalAlign.Center;
                            break;
                        case FvGridAlignment.Right:
                            oCell.HorizontalAlign = HorizontalAlign.Right;
                            break;
                    }
                    oCell.Text = oColHeader.ColumnName;
                    if (oColHeader.Width != null)
                        oCell.Style.Add(HtmlTextWriterStyle.Width, Convert.ToString(oColHeader.Width) + "px");
                    if (HeaderCssClass != null)
                        oCell.Attributes.Add("class", HeaderCssClass);
                    oCell.Style.Add("white-space""nowrap");
                    if (GridCellBinding != null)
                    {
                        FvGridCellBindingArgs oCArgs = new FvGridCellBindingArgs();
                        oCArgs.DataRow = null;
                        oCArgs.ItemCell = oCell;
                        oCArgs.Column = oColHeader;
                        oCArgs.CommandArgs = this.CommandArgs;
                        oCArgs.RowType = FvGridRowType.Header;
                        GridCellBinding(this, oCArgs);
                    }
                    oRowHeader.Cells.Add(oCell);
                }
                if (GridRowBinding != null)
                {
                    FvGridRowBindingArgs oArgs = new FvGridRowBindingArgs();
                    oArgs.DataRow = null;
                    oArgs.ItemRow = oRowHeader;
                    oArgs.CommandArgs = this.CommandArgs;
                    oArgs.ItemRows = oRowHeader.Cells;
                    oArgs.RowType = FvGridRowType.Header;
                    GridRowBinding(this, oArgs);
                }
            }
        }
        #endregion

        #region IStateManager Members
        bool IStateManager.IsTrackingViewState
        {
            get
            {
                return ((IStateManager)_viewstate).IsTrackingViewState;
            }
        }
        void IStateManager.LoadViewState(object savedState)
        {
            FreezHeader = (Boolean)_viewstate["FreezHeader"];
            ShowGroupColumn = (Boolean)_viewstate["ShowGroupColumn"];
            Width = (Unit)_viewstate["Width"];
            Height = (Unit)_viewstate["Height"];
            OnClientRowClick = (String)_viewstate["OnClientRowClick"];
            OnClientRowDblClick = (String)_viewstate["OnClientRowDblClick"];
            DataSource = (DataTable)_viewstate["DataSource"];
            CommandArgs = (String)_viewstate["CommandArgs"];
            _Columns = (FvGridColumns)_viewstate["_Columns"];
            _Groups = (FvGridGroups)_viewstate["_Groups"];
            ColumnLable = (Int32)_viewstate["ColumnLable"];

            CssClass = (String)_viewstate["CssClass"];
            HeaderCssClass = (String)_viewstate["HeaderCssClass"];
            AlternateRowCssClass = (String)_viewstate["AlternateRowCssClass"];
            RowCssClass = (String)_viewstate["RowCssClass"];
            FooterCssClass = (String)_viewstate["FooterCssClass"];

            if (savedState != null)
                ((IStateManager)_viewstate).LoadViewState(savedState);
        }
        object IStateManager.SaveViewState()
        {
            _viewstate.Clear();
            // Add the _message property to the StateBag.
            _viewstate.Add("FreezHeader", FreezHeader);
            _viewstate.Add("ShowGroupColumn", ShowGroupColumn);
            _viewstate.Add("Width", Width);
            _viewstate.Add("Height", Height);
            _viewstate.Add("OnClientRowClick", OnClientRowClick);
            _viewstate.Add("OnClientRowDblClick", OnClientRowDblClick);
            _viewstate.Add("DataSource", DataSource);
            _viewstate.Add("CommandArgs", CommandArgs);
            _viewstate.Add("_Columns", _Columns);
            _viewstate.Add("_Groups", _Groups);
            _viewstate.Add("ColumnLable", ColumnLable);

            _viewstate.Add("CssClass", CssClass);
            _viewstate.Add("HeaderCssClass", HeaderCssClass);
            _viewstate.Add("RowCssClass", RowCssClass);
            _viewstate.Add("AlternateRowCssClass", AlternateRowCssClass);
            _viewstate.Add("FooterCssClass", FooterCssClass);

            return ((IStateManager)_viewstate).SaveViewState();
        }
        void IStateManager.TrackViewState()
        {
            ((IStateManager)_viewstate).TrackViewState();
        }
        #endregion
    }
    public delegate void FvGridRowBinding(Object sender, FvGridRowBindingArgs e);
    public delegate void FvGridCellBinding(Object sender, FvGridCellBindingArgs e);
    public enum FvGridRowType
    {
        Header,
        Row,
        AlternateRow,
        GroupRow,
        Footer
    }
    public enum FvGridRowGroupOperation
    {
        None, Sum, Avg, Count
    }
    public enum FvGridAlignment
    {
        Left,
        Center,
        Right
    }
    public class FvGridRowBindingArgs : EventArgs
    {
        /// <summary>
        /// Get the current DataRow from the DataSource
        /// </summary>
        public DataRow DataRow
        {
            get;
            internal set;
        }
        /// <summary>
        /// Get the ItemRow
        /// </summary>
        public TableRow ItemRow
        {
            get;
            set;
        }
        /// <summary>
        /// Get the ItemRow Collection
        /// </summary>
        public TableCellCollection ItemRows
        {
            get;
            set;
        }
        /// <summary>
        /// Get the Type of row
        /// </summary>
        public FvGridRowType RowType
        {
            get;
            set;
        }
        public String CommandArgs
        {
            get;
            internal set;
        }
    }
    public class FvGridCellBindingArgs : EventArgs
    {
        /// <summary>
        /// Get the current DataRow from the DataSource
        /// </summary>
        public DataRow DataRow
        {
            get;
            internal set;
        }
        /// <summary>
        /// Get the ItemCell
        /// </summary>
        public TableCell ItemCell
        {
            get;
            set;
        }
        public FvGridColumn Column
        {
            get;
            set;
        }
        public FvGridRowType RowType
        {
            get;
            set;
        }
        public String CommandArgs
        {
            get;
            internal set;
        }
    }
    public class FvGridColumn : IStateManager
    {
        #region Private Variables
        private StateBag _viewstate;
        private String _DataField;
        private String _ColumnName;
        private String _DataFormat;
        private Int32 _Width;
        private FvGridAlignment _Alignment;
        private FvGridColumns _Columns;
        private Int32 _ColSpan;
        private Int32 _RowSpan;
        #endregion

        #region Constrator
        public FvGridColumn()
        {
            //_Columns = new FvGridColumns();
            _viewstate = new StateBag();
            _viewstate.Add("DataField", _DataField);
            _viewstate.Add("ColumnName", _ColumnName);
            _viewstate.Add("DataFormat", _DataFormat);
            _viewstate.Add("Width", _Width);
            _viewstate.Add("Alignment", _Alignment);
            _viewstate.Add("Columns", _Columns);
            _viewstate.Add("ColSpan", _ColSpan);
            _viewstate.Add("RowSpan", _RowSpan);
        }
        #endregion

        #region Properties
        public String DataField
        {
            get
            {
                return (String)_viewstate["DataField"];
            }
            set
            {
                _DataField = value;
                _viewstate["DataField"] = value;
                _viewstate.SetItemDirty("DataField"true);
            }
        }
        public String ColumnName
        {
            get
            {
                return (String)_viewstate["ColumnName"];
            }
            set
            {
                _ColumnName = value;
                _viewstate["ColumnName"] = value;
                _viewstate.SetItemDirty("ColumnName"true);
            }
        }
        public String DataFormat
        {
            get
            {
                return (String)_viewstate["DataFormat"];
            }
            set
            {
                _DataFormat = value;
                _viewstate["DataFormat"] = value;
                _viewstate.SetItemDirty("DataFormat"true);
            }
        }
        public Int32? Width
        {
            get
            {
                return (Int32)_viewstate["Width"];
            }
            set
            {
                _Width = Convert.ToInt32(value);
                _viewstate["Width"] = value;
                _viewstate.SetItemDirty("Width"true);
            }
        }
        public FvGridAlignment Alignment
        {
            get
            {
                return (FvGridAlignment)_viewstate["Alignment"];
            }
            set
            {
                _Alignment = value;
                _viewstate["Alignment"] = value;
                _viewstate.SetItemDirty("Alignment"true);
            }
        }
        /// <summary>
        /// Sub Columns
        /// </summary>
        public FvGridColumns Columns
        {
            get
            {
                if (_Columns == null && _viewstate["Columns"] == null)
                {
                    _Columns = new FvGridColumns();
                    _viewstate["Columns"] = _Columns;
                }
                return (FvGridColumns)_viewstate["Columns"];
            }
            set
            {
                _Columns = value;
                _viewstate["Columns"] = value;
                _viewstate.SetItemDirty("Columns"true);
            }
        }
        public Int32 ColSpan
        {
            get
            {
                return (Int32)_viewstate["ColSpan"];
            }
            set
            {
                _ColSpan = value;
                _viewstate["ColSpan"] = value;
                _viewstate.SetItemDirty("ColSpan"true);
            }
        }
        public Int32 RowSpan
        {
            get
            {
                return (Int32)_viewstate["RowSpan"];
            }
            set
            {
                _RowSpan = value;
                _viewstate["RowSpan"] = value;
                _viewstate.SetItemDirty("RowSpan"true);
            }
        }
        #endregion

        #region IStateManager Members
        bool IStateManager.IsTrackingViewState
        {
            get
            {
                return ((IStateManager)_viewstate).IsTrackingViewState;
            }
        }
        void IStateManager.LoadViewState(object savedState)
        {
            DataField = (string)_viewstate["DataField"];
            ColumnName = (string)_viewstate["ColumnName"];
            DataFormat = (string)_viewstate["DataFormat"];
            Width = (Int32)_viewstate["Width"];
            Alignment = (FvGridAlignment)_viewstate["Alignment"];
            Columns = (FvGridColumns)_viewstate["Columns"];
            ColSpan = (Int32)_viewstate["ColSpan"];
            RowSpan = (Int32)_viewstate["RowSpan"];

            if (savedState != null)
                ((IStateManager)_viewstate).LoadViewState(savedState);
        }
        object IStateManager.SaveViewState()
        {
            _viewstate.Clear();
            // Add the _message property to the StateBag.
            _viewstate.Add("DataField", _DataField);
            _viewstate.Add("ColumnName", _ColumnName);
            _viewstate.Add("DataFormat", _DataFormat);
            _viewstate.Add("Width", _Width);
            _viewstate.Add("Alignment", _Alignment);
            _viewstate.Add("Columns", _Columns);
            _viewstate.Add("ColSpan", _ColSpan);
            _viewstate.Add("RowSpan", _RowSpan);
            return ((IStateManager)_viewstate).SaveViewState();
        }
        void IStateManager.TrackViewState()
        {
            ((IStateManager)_viewstate).TrackViewState();
        }
        #endregion
    }
    public class FvGridGroup : IStateManager
    {
        #region Private Variables
        private StateBag _viewstate;
        private String _DataField;
        private String _CssClass;
        private FvGridRowGroupOperation _Operation;
        #endregion

        #region Constractor
        public FvGridGroup()
        {
            _Operation = FvGridRowGroupOperation.None;
            _viewstate = new StateBag();
            _viewstate.Add("DataField", _DataField);
            _viewstate.Add("Operation", _Operation);
            _viewstate.Add("CssClass", _CssClass);
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the DataField for the Group Column
        /// </summary>
        public String DataField
        {
            get
            {
                return (String)_viewstate["DataField"];
            }
            set
            {
                _DataField = value;
                _viewstate["DataField"] = value;
                _viewstate.SetItemDirty("DataField"true);
            }
        }
        /// <summary>
        /// Gets or sets the Operation for the Group Column
        /// </summary>
        public FvGridRowGroupOperation Operation
        {
            get
            {
                return (FvGridRowGroupOperation)_viewstate["Operation"];
            }
            set
            {
                _Operation = value;
                _viewstate["Operation"] = value;
                _viewstate.SetItemDirty("Operation"true);
            }
        }
        /// <summary>
        /// Gets or sets the Cascading Style Sheet (CSS) class on Group Row
        /// rendered by the Web server control on the client.
        /// </summary>
        public String CssClass
        {
            get
            {
                return (String)_viewstate["CssClass"];
            }
            set
            {
                _DataField = value;
                _viewstate["CssClass"] = value;
                _viewstate.SetItemDirty("CssClass"true);
            }
        }
        #endregion

        #region IStateManager Members
        bool IStateManager.IsTrackingViewState
        {
            get
            {
                return ((IStateManager)_viewstate).IsTrackingViewState;
            }
        }
        void IStateManager.LoadViewState(object savedState)
        {
            DataField = (string)_viewstate["DataField"];
            Operation = (FvGridRowGroupOperation)_viewstate["Operation"];
            CssClass = (String)_viewstate["CssClass"];
            if (savedState != null)
                ((IStateManager)_viewstate).LoadViewState(savedState);
        }
        object IStateManager.SaveViewState()
        {
            _viewstate.Clear();
            // Add the _message property to the StateBag.
            _viewstate.Add("DataField", _DataField);
            _viewstate.Add("Operation", _Operation);
            _viewstate.Add("CssClass", _CssClass);
            return ((IStateManager)_viewstate).SaveViewState();
        }
        void IStateManager.TrackViewState()
        {
            ((IStateManager)_viewstate).TrackViewState();
        }

        #endregion
    }
    public class FvGridColumns : FvStateCollection<FvGridColumn>
    {
        new public FvGridColumn Add(FvGridColumn o)
        {
            base.Add(o);
            return o;
        }
    }
    public class FvGridGroups : FvStateCollection<FvGridGroup>
    {
    }
    public class FvStateCollection<T> : List<T>, IStateManager
        where T : IStateManager, new()
    {
        #region Fields
        bool _tracking;
        #endregion

        #region Properties
        /// <summary>
        /// When implemented by a class, gets a value indicating whether a server control is tracking its view state changes.
        /// </summary>
        /// <value></value>
        /// <returns>true if a server control is tracking its view state changes; otherwise, false.</returns>
        public bool IsTrackingViewState
        {
            get { return _tracking; }
        }
        #endregion

        #region Methods

        /// <summary>
        /// Loads the state of the view.
        /// </summary>
        /// <param name="savedState">State of the saved.</param>
        public void LoadViewState(object savedState)
        {
            object[] state = savedState as object[];
            if (state != null)
            {
                T item;
                bool exists;
                for (int i = 0; i < state.Length; i++)
                {
                    item = (exists = (i < this.Count)) ? this[i] : new T();
                    item.LoadViewState(state[i]);
                    if (this.IsTrackingViewState)
                        item.TrackViewState();
                    if (!exists) Add(item);
                }
            }
        }

        /// <summary>
        /// When implemented by a class, saves the changes to a server control's view state to an <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// The <see cref="T:System.Object"/> that contains the view state changes.
        /// </returns>
        public object SaveViewState()
        {
            if (this.Count > 0)
            {
                int count = this.Count;
                object[] state = new object[count];
                for (int i = 0; i < count; i++)
                {
                    state[i] = this[i].SaveViewState();
                }
                return state;
            }
            else
                return null;
        }

        /// <summary>
        /// When implemented by a class, instructs the server control to track changes to its view state.
        /// </summary>
        public void TrackViewState()
        {
            _tracking = true;
        }
        #endregion
    }
}

Aspx Code for Using the Custom Grid
Registering the control on Web pages
<%@ Register Assembly="Fv.Web.UI" Namespace="Fv.Web.UI" TagPrefix="cc1" %>

Using the Control
<div>
        <cc1:FvGrid ID="FvGrid1" runat="server" PadddingLeft="25" >
            <Columns>
                <cc1:FvGridColumn DataField="DESCR" ColumnName="DESCR" Alignment="Left" Width="315" />
                <cc1:FvGridColumn DataField="ACCD" ColumnName="ACCD" Alignment="Left" Width="260" />
                <cc1:FvGridColumn DataField="DOCNO" ColumnName="DOCNO" Alignment="Left" Width="260"/>
            </Columns>
            <Groups>
                <cc1:FvGridGroup DataField="DESCR" Operation="None" />
            </Groups>
        </cc1:FvGrid>
    </div>
Aspx.cs Code for Using the Custom Grid
DataSet dsData = oo.GetDataSet(HttpContext.Current.Session.Contents["ConnectionInfo"].ToString(),
                          HttpContext.Current.Session.Contents["Provider"].ToString(),
                          "SELECT DISTINCT top 10 B.DESCR,ACCD,DOCNO FROM SALE_TFA_IT A INNER JOIN M_ITEM B ON A.ITEMCD = B.ITEMCD ORDER BY B.DESCR,ACCD,DOCNO");

FvGrid1.Width = Unit.Percentage(100);
FvGrid1.Height = Unit.Pixel(300);
FvGrid1.FreezHeader = false;
FvGrid1.CssClass = "RadGrid_Office2007";
FvGrid1.HeaderCssClass = "GridHeader_Office2007";
FvGrid1.RowCssClass = "GridRow_Office2007";
FvGrid1.AlternateRowCssClass = "GridAltRow_Office2007";

//FvGrid1.GridRowBinding += new GridRowBinding(o_GridRowBinding);
* FvGrid1.Columns.Add(new FvGridColumn()
{
    ColumnName = "DESCR",
    DataField = "DESCR",
    Alignment = FvGridAlignment.Left,
    Width = 315
});
FvGrid1.Columns.Add(new FvGridColumn()
{
     ColumnName = "ACCD",
     DataField = "ACCD",
     Alignment = FvGridAlignment.Left,
     Width = 260
 });
 FvGrid1.Columns.Add(new FvGridColumn()
 {
     ColumnName = "DOCNO",
     DataField = "DOCNO",
     Alignment = FvGridAlignment.Left,
     Width = 260
 });
FvGrid1.Groups.Add(new FvGridGroup() { DataField = "DESCR" });
FvGrid1.Groups.Add(new FvGridGroup() { DataField = "ACCD" });*/
FvGrid1.DataSource = dsData.Tables[0];
FvGrid1.DataBind();
Note: The comment line for without the design part of aspx page

Posted By: Mr. Palash Paul


1 comment: