Click here to Skip to main content
13,592,615 members
Click here to Skip to main content

Stats

188.4K views
11.3K downloads
134 bookmarked
Posted 27 Sep 2010
Licenced CPOL

Group GridView Data

, 22 Aug 2014
A custom GridView control which provides you an additional facility to group the data in gridview along with the facility to customise the Group Header and Group Footer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;
using System.Collections;
using System.Data;

// Written by Anurag Gandhi.
// Url: http://www.gandhisoft.com
// Contact me at: soft.gandhi@gmail.com

namespace GroupGridViewCtrl
{
    public class GroupGridView : GridView
    {
        private ITemplate _GroupHeaderTemplate;
        private ITemplate _GroupFooterTemplate;
        private int _totalColumns;

        private DefaultState _DefaultState = DefaultState.Expanded;

        public DefaultState DefaultState
        {
            get { return _DefaultState; }
            set { _DefaultState = value; }
        }

        private Animation _AnimationSpeed = Animation.Fast;

        public Animation AnimationSpeed
        {
            get { return _AnimationSpeed; }
            set { _AnimationSpeed = value; }
        }

        private bool _AllowGrouping = false;

        public bool AllowGrouping
        {
            get { return _AllowGrouping; }
            set { _AllowGrouping = value; }
        }
        private string _GroupColumnName = string.Empty;

        public string GroupColumnName
        {
            get { return _GroupColumnName; }
            set { _GroupColumnName = value; }
        }

        [Browsable(false)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(GroupContainer))]
        public ITemplate GroupHeaderTemplate
        {
            get { return _GroupHeaderTemplate; }
            set { _GroupHeaderTemplate = value; }
        }

        [Browsable(false)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(GroupContainer))]
        public ITemplate GroupFooterTemplate
        {
            get { return _GroupFooterTemplate; }
            set { _GroupFooterTemplate = value; }
        }

        /// <summary>
        /// OverRiding PrepareControlHierarchy to instanciate the GroupHeader and GroupFooter Rows also in our GridView.//
        /// </summary>
        protected override void PrepareControlHierarchy()
        {
            base.PrepareControlHierarchy();

            Table t = (Table)Controls[0];
            if ((_GroupHeaderTemplate != null || _GroupFooterTemplate != null) && !String.IsNullOrEmpty(_GroupColumnName) && _AllowGrouping == true)
            {
                TableRow row = new TableRow();
                row.Style.Add("display", "none");
                t.Rows.AddAt(0, row);
                TableCell cell = new TableCell();
                cell.ColumnSpan = _totalColumns;
                row.Cells.Add(cell);

                DataTable _SourceTable = (DataTable)this.DataSource;
                var GroupList = (from x in _SourceTable.AsEnumerable() select new { Data = x.Field<object>(_GroupColumnName) }).Distinct();
                foreach (var Group in GroupList)
                {
                    if (_GroupHeaderTemplate != null)
                    {
                        GroupContainer HeaderContainer = new GroupContainer(this, _GroupColumnName, Group.Data);
                        _GroupHeaderTemplate.InstantiateIn(HeaderContainer);
                        Panel pHeader = new Panel();
                        pHeader.Attributes.Add("id", this.ClientID + "_GroupHeader_" + GetGroupData(Group.Data));
                        pHeader.Controls.Add(HeaderContainer);
                        cell.Controls.Add(pHeader);
                    }
                    if (_GroupFooterTemplate != null)
                    {
                        GroupContainer FooterContainer = new GroupContainer(this, _GroupColumnName, Group.Data);
                        _GroupFooterTemplate.InstantiateIn(FooterContainer);
                        Panel pFooter = new Panel();
                        pFooter.Attributes.Add("id", this.ClientID + "_GroupFooter_" + GetGroupData(Group.Data));
                        pFooter.Controls.Add(FooterContainer);
                        cell.Controls.Add(pFooter);
                    }
                }
                cell.DataBind();
            }
            return;
        }

        /// <summary>
        /// OverRiding OnRowCreated method.//
        /// </summary>
        /// <param name="e"></param>
        protected override void OnRowCreated(GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                //Adding "group" attribute to each row of the resulting table.//
                string GroupValue = GetGroupData(DataBinder.Eval(e.Row.DataItem, _GroupColumnName));
                e.Row.Attributes.Add("group", GroupValue);
            }
            base.OnRowCreated(e);
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            RenderClientSideGroup();
        }
        
        /// <summary>
        /// Overriding CreateColumns to get the total number of columns in GridView.//
        /// </summary>
        /// <param name="dataSource"></param>
        /// <param name="useDataSource"></param>
        /// <returns></returns>
        protected override ICollection CreateColumns(PagedDataSource dataSource, bool useDataSource)
        {
            ICollection coll = base.CreateColumns(dataSource, useDataSource);
            _totalColumns = coll.Count;
            return coll;
        }

        /// <summary>
        /// This is to remove any special character which may cause problem for javascript to run.//
        /// </summary>
        /// <param name="obj">Data based on which grouping needs to be done.</param>
        /// <returns>Data based on which grouping needs to be done (without special chars)</returns>
        private string GetGroupData(object obj)
        {
            string strData = Convert.ToString(obj);
            strData = strData.Replace(" ", "_");
            strData = strData.Replace("&", "_");
            return strData;
        }

        /// <summary>
        /// Renders the javascript/jquery to perform client side operation for grouping.//
        /// </summary>
        /// <returns>returns true if succeed</returns>
        public bool RenderClientSideGroup()
        {
            int ColCount = _totalColumns;
            string GridViewId = this.ClientID;
            string FadeOutScript, FadeInScript;

            switch (_AnimationSpeed)
            {
                case Animation.None:
                    FadeInScript = ".css('display', '')";
                    FadeOutScript = ".css('display', 'none')";
                    break;
                case Animation.Fast:
                    FadeInScript = ".fadeIn('fast')";
                    FadeOutScript = ".fadeOut('fast')";
                    break;
                case Animation.Slow:
                    FadeInScript = ".fadeIn('slow')";
                    FadeOutScript = ".fadeOut('slow')";
                    break;
                default:
                    FadeInScript = ".fadeIn()";
                    FadeOutScript = ".fadeOut()";
                    break;
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine(" $(document).ready(function () {");
            sb.AppendLine("ApplyGrouping_" + this.ClientID + "();");
            if (this.DefaultState == GroupGridViewCtrl.DefaultState.Collapsed)
            {
                sb.AppendLine(string.Format(" $('#{0} tr[group]'){1};", GridViewId, FadeOutScript));
                sb.AppendLine(" $('#" + GridViewId + " tr[id^=GroupHeader]').attr('expanded', 'false');");
            }
            sb.AppendLine(" });");

            sb.AppendLine(" function ApplyGrouping_" + this.ClientID + "() {");
            sb.AppendLine(" var PrevText = '###', CurrText = '';");
            //sb.AppendLine(" $('#" + GridViewId + " tr:gt(1)').each(function (index) {");
            sb.AppendLine(" $('#" + GridViewId + " tr[group]').each(function (index) {");
            sb.AppendLine(" CurrText = $(this).attr('group');");
            sb.AppendLine(" if (PrevText != CurrText) {");
            //For Displaying Group Header and Footer.//
            if (_GroupFooterTemplate != null)
            {
                sb.AppendLine(" if (PrevText != '###' && $('#" + this.ClientID + "_GroupFooter_' + PrevText).length != 0)");
                sb.AppendLine(string.Format(" $(this).before('<tr id=\"GroupFooter' + PrevText + '\" expanded=\"true\"><td colspan=\"{0}\">' + $('#" + this.ClientID + "_GroupFooter_' + PrevText).html() + '</td></tr>');", ColCount));
            }
            sb.AppendLine(string.Format(" $(this).before('<tr id=\"GroupHeader' + CurrText + '\" expanded=\"true\" onclick=\"javascript:return Clicked_{1}(\\'' + CurrText + '\\');\" style=\"cursor:pointer;\"><td colspan=\"{0}\">' + $('#" + this.ClientID + "_GroupHeader_' + CurrText).html() + '</td></tr>');", ColCount, this.ClientID));
            sb.AppendLine("}");

            if (_GroupFooterTemplate != null)
            {
                sb.AppendLine(" if (index == " + (this.Rows.Count - 1).ToString() + " && $('#" + this.ClientID + "_GroupFooter_' + CurrText).length != 0)");
                sb.AppendLine(string.Format(" $(this).after('<tr id=\"GroupFooter' + CurrText + '\" expanded=\"true\"><td colspan=\"{0}\">' + $('#" + this.ClientID + "_GroupFooter_' + CurrText).html() + '</td></tr>');", ColCount));
            }
            sb.AppendLine(" PrevText = CurrText;");
            sb.AppendLine(" });");
            sb.AppendLine("}");

            sb.AppendLine(" ");
            sb.AppendFormat(" function Clicked_{0}(GroupId) {{", this.ClientID);
            sb.AppendLine(" if ($('#" + GridViewId + " tr#GroupHeader' + GroupId).attr('expanded') == 'true') {");
            sb.AppendLine(string.Format(" $('#{0} tr[group=' + GroupId + ']'){1};", GridViewId, FadeOutScript));
            sb.AppendLine(" $('#" + GridViewId + " tr#GroupHeader' + GroupId).attr('expanded', 'false');");
            sb.AppendLine(" }");
            sb.AppendLine(" else {");
            sb.AppendLine(string.Format(" $('#{0} tr[group=' + GroupId + ']'){1};", GridViewId, FadeInScript));
            sb.AppendLine(" $('#" + GridViewId + " tr#GroupHeader' + GroupId).attr('expanded', 'true');");
            sb.AppendLine(" }");
            sb.AppendLine(" }");

            this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "GroupScript" + this.ClientID, sb.ToString(), true);
            return true;
        }
    }

    /// <summary>
    /// Animation to decide the speed of FadeIn and FadeOut action.//
    /// </summary>
    public enum Animation
    {
        None = 0,
        Fast = 1,
        Slow = 2
    }

    public enum DefaultState
    {
        Collapsed = 0,
        Expanded = 1
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Anurag Gandhi
Architect
India India
Anurag Gandhi is a Developer, Consultant, Architect, Blogger, Speaker and a Microsoft Employee. He is passionate about programming.
He is extensively involved in Asp.Net Core, MVC/Web API, Microsoft Azure/Cloud, web application hosting/architecture, Angular, AngularJs, design and development. His languages of choice are C#, Node/Express, JavaScript, Asp .NET MVC, Asp, C, C++. He is familiar with many other programming languages as well. He mostly works with MS Sql Server as the preferred database and has worked with Redis, MySQL, Oracle, MS Access, etc. also.
He is active in programming communities and loves to share the knowledge with others whenever he gets the time for it.
He is also a passionate chess player.
Linked in Profile: https://in.linkedin.com/in/anuraggandhi
He can be contacted at: soft.gandhi@gmail.com

Disclaimer: Any posts, article, content present in this website is my personal opinion based on best of my knowledge and experience. None of the content provided by me should be considered as official communication/opinion or my Employer.

You may also be interested in...

Pro
Pro
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02-2016 | 2.8.180618.1 | Last Updated 22 Aug 2014
Article Copyright 2010 by Anurag Gandhi
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid